#include #include using namespace std; using namespace atcoder; //using mint = modint1000000007; //const int mod = 1000000007; //using mint = modint998244353; //const int mod = 998244353; //const int INF = 1e9; //const long long LINF = 1e18; #define rep(i, n) for (int i = 0; i < (n); ++i) #define rep2(i,l,r)for(int i=(l);i<(r);++i) #define rrep(i, n) for (int i = (n-1); i >= 0; --i) #define rrep2(i,l,r)for(int i=(r-1);i>=(l);--i) #define all(x) (x).begin(),(x).end() #define allR(x) (x).rbegin(),(x).rend() #define endl "\n" #define P pair template inline bool chmax(A & a, const B & b) { if (a < b) { a = b; return true; } return false; } template inline bool chmin(A & a, const B & b) { if (a > b) { a = b; return true; } return false; } struct trie { int kind; vectornode; vector>next; vectorend; trie(int _kind) :kind(_kind) { node.resize(1); end.resize(1); next.emplace_back(vector(kind, -1)); } void insert(const vector&v) { int now = 0; rep(i, v.size()) { if (-1 == next[now][v[i]]) { next[now][v[i]] = node.size(); node.emplace_back(0); end.push_back(false); next.emplace_back(vector(kind, -1)); } now = next[now][v[i]]; node[now]++; } end[now] = true; } bool seach(const vector&v) { int now = 0; rep(i, v.size()) { if (-1 == next[now][v[i]])return false; if (node[next[now][v[i]]] <= 0)return false; now = next[now][v[i]]; } return end[now]; } void erase(const vector&v) { int now = 0; rep(i, v.size()) { now = next[now][v[i]]; node[now]--; } end[now] = false; } // prefixも取得する vector getIndexEx(const vector&v) { vectorret; int idx = 0, now = 0; rep(i, v.size()) { if (0 != now) { idx += node[now]; rep(j, 2)if (-1 != next[now][j])idx -= node[next[now][j]]; } if (0 == v[i]) { if (-1 == next[now][v[i]])break; now = next[now][v[i]]; } else { if (-1 != next[now][0]) idx += node[next[now][0]]; if (-1 == next[now][v[i]])break; now = next[now][v[i]]; } ret.push_back(now); } return ret; } }; vector trans(string s) { vectorret(s.size()); rep(i, s.size()) ret[i] = s[i] - 'a'; return ret; } using S = long long; S op(S a, S b) { return a + b; } S e() { return 0; } struct HeavyLightDecomposition { HeavyLightDecomposition(vector> &_g, vector&_val) :g(_g), val(_val) { n = g.size(); sz.resize(n); par.resize(n); in.resize(n); out.resize(n); rev.resize(n); head.resize(n); } int n; vector>g; vectorsz, par, in, out, rev, head; vectorval; segtreeseg; void build() { dfs_sz(0); int time = 0; dfs_hld(0, time); initSegmentTree(); } void dfs_sz(int v, int p = -1) { par[v] = p; sz[v] = 1; if (g[v].size() && (p == g[v][0]))swap(g[v][0], g[v].back()); for (auto &e : g[v]) { if (p == e)continue; dfs_sz(e, v); sz[v] += sz[e]; if (sz[g[v][0]] < sz[e])swap(g[v][0], e); } } void dfs_hld(int v, int &time, int p = -1) { in[v] = time; time++; rev[in[v]] = v; for (auto &e : g[v]) { if (p == e)continue; if (e == g[v][0])head[e] = head[v]; else head[e] = e; dfs_hld(e, time, v); } out[v] = time; } void initSegmentTree() { vector_val(n); rep(i, n)_val[i] = val[rev[i]]; segtree _seg(_val); seg = _seg; } S query(int u, int v) { S ret = e(); for (;; v = par[head[v]]) { if (in[u] > in[v])swap(u, v); if (head[u] == head[v])break; auto get = seg.prod(in[head[v]], in[v] + 1); ret = op(ret, get); } auto get = seg.prod(in[u], in[v] + 1); ret = op(ret, get); return ret; } int la(int v, int k) { while (1) { int u = head[v]; if (in[v] - k > in[u])return rev[in[v] - k]; k -= in[v] - in[u] + 1; v = par[u]; } } int lca(int u, int v) { for (;; v = par[head[v]]) { if (in[u] > in[v])swap(u, v); if (head[u] == head[v])return u; } } // point update void update_point(int u, S x) { auto get = seg.get(in[u]); seg.set(in[u], get + 1); } void debug() { rep(i, n) cout << seg.prod(i, i + 1) << " "; cout << endl; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vectors(n); rep(i, n)cin >> s[i]; int q; cin >> q; vectort(q), x(q); vectorc(q); vectors2 = s; rep(i, q) { cin >> t[i] >> x[i], x[i]--; if (1 == t[i]) { cin >> c[i]; s2[x[i]] += c[i]; } } trie tr(26); rep(i, n)tr.insert(trans(s2[i])); vector>idx(n); rep(i, n) idx[i] = tr.getIndexEx(trans(s2[i])); int sz = 0; rep(i, n) chmax(sz, idx[i].back() + 1); vectorv(sz); rep(i, n)rep(j, s[i].size()) v[idx[i][j]]++; vector>g(sz); rep(i, n) rep(j, idx[i].size()) { int u = 0, v = 0; if (0 != j)u = idx[i][j - 1]; v = idx[i][j]; g[u].push_back(v); g[v].push_back(u); } rep(i, g.size()) { sort(all(g[i])); g[i].erase(unique(all(g[i])), g[i].end()); } HeavyLightDecomposition hld(g, v); hld.build(); vectornow(n); rep(i, n)now[i] = s[i].size(); rep(i, q) { if (1 == t[i]) { hld.update_point(idx[x[i]][now[x[i]]], 1); now[x[i]]++; } else { S ans = hld.query(0, idx[x[i]][now[x[i]] - 1]); cout << ans << endl; } } return 0; }