#include #include #include namespace nachia { struct LinkCutTree { struct S { unsigned int x; }; static S op(S l, S r) { return { l.x + r.x }; } static S e() { return { 0 }; } static void reverseprod(S& x) {} struct F { }; static S mapping(F f, S x) { return x; } static F composition(F f, F x) { return x; } static F id() { return {}; } struct Node { Node* l = 0, * r = 0, * p = 0; S a = e(); S prod = e(); F f = id(); // lazy & 1 : reverse // lazy & 2 : deta int lazy = 0; void prepareDown() { if(lazy & 2){ if(l) { l->a = mapping(f, l->a); l->prod = mapping(f, l->prod); l->f = composition(f, l->f); l->lazy |= 2; } if(r) { r->a = mapping(f, r->a); r->prod = mapping(f, r->prod); r->f = composition(f, r->f); r->lazy |= 2; } f = id(); } if (lazy & 1) { ::std::swap(l, r); if (l) { l->lazy ^= 1; reverseprod(l->prod); } if (r) { r->lazy ^= 1; reverseprod(r->prod); } } lazy = 0; } void prepareUp() { auto res = a; if(l) res = op(l->prod, res); if(r) res = op(res, r->prod); prod = res; } Node** p_parentchild() { if(!p) return nullptr; if(p->l == this) return &p->l; else if(p->r == this) return &p->r; return nullptr; } void rotL() { Node* t = p; Node** parentchild_p = t->p_parentchild(); if(parentchild_p){ *parentchild_p = this; } p = t->p; t->p = this; t->r = l; if(l) l->p = t; l = t; } void rotR() { Node* t = p; Node** parentchild_p = t->p_parentchild(); if(parentchild_p){ *parentchild_p = this; } p = t->p; t->p = this; t->l = r; if(r) r->p = t; r = t; } }; ::std::vector A; LinkCutTree(int n = 0) { A.resize(n); } LinkCutTree(const ::std::vector& a) : LinkCutTree(a.size()) { for (int i = 0; i < (int)a.size(); i++) A[i].prod = A[i].a = a[i]; } Node* at(int idx) { return &A[idx]; } void splay(Node* c) { c->prepareDown(); while(true) { Node* p = c->p; if(!p) break; Node* pp = p->p; if(pp) pp->prepareDown(); p->prepareDown(); c->prepareDown(); if(p->l == c){ if(!pp){ c->rotR(); } else if(pp->l == p){ p->rotR(); c->rotR(); } else if(pp->r == p){ c->rotR(); c->rotL(); } else{ c->rotR(); } } else if(p->r == c){ if(!pp){ c->rotL(); } else if(pp->r == p){ p->rotL(); c->rotL(); } else if(pp->l == p){ c->rotL(); c->rotR(); } else{ c->rotL(); } } else break; if(pp) pp->prepareUp(); p->prepareUp(); } c->prepareUp(); } void expose(Node* c) { auto p = c; while(p){ splay(p); p = p->p; } p = c; while(p->p){ p->p->r = p; p = p->p; } splay(c); c->r = nullptr; c->prod = (c->l ? op(c->l->prod, c->a) : c->a); } void evert(Node* c) { expose(c); c->lazy ^= 1; reverseprod(c->prod); c->prepareDown(); } void link(Node* c, Node* r) { if(c == r) return; evert(c); evert(r); if(c->p) return; c->p = r; } void cut(Node* c) { expose(c); if(!c->l) return; c->l->p = nullptr; c->l = nullptr; } // [u,v) // post : evert(u) , splayLC(v) Node* between(Node* u, Node* v) { if(u == v) return nullptr; evert(u); expose(v); v->l->prepareDown(); return v->l; } S prod(Node* s, Node* t) { auto resv = between(s, t); if(!resv) return t->a; S res = resv->prod; res = op(res, t->a); return res; } S get(Node* p) { expose(p); return p->a; } void set(Node* p, S x) { expose(p); p->a = x; p->prepareUp(); } }; } #include #include #include #include #include using namespace std; using i32 = int32_t; using u32 = uint32_t; using i64 = int64_t; using u64 = uint64_t; #define rep(i,n) for(int i=0; i<(int)(n); i++) const i64 INF = 1001001001001001001; using modint = atcoder::static_modint<998244353>; int N, Q; vector S; int nx[410000][26]; vector pos; int NN; pair getNext(int p, char c){ int& dst = nx[p][c-'a']; if(dst == -1) return make_pair(dst = NN++, true); return make_pair(dst, false); } int main(){ cin >> N; S.resize(N); rep(i,N) cin >> S[i]; nachia::LinkCutTree lct(410000); cin >> Q; int Z = Q + 1; for(auto& s : S) Z += s.size(); rep(i,Z) rep(t,26) nx[i][t] = -1; NN = 1; pos.assign(N, 0); rep(i,N) for(char c : S[i]){ auto [nx,isnew] = getNext(pos[i], c); if(isnew){ lct.set(lct.at(nx), {1}); lct.link(lct.at(nx), lct.at(pos[i])); } else{ lct.set(lct.at(nx), { lct.get(lct.at(nx)).x + 1 }); } pos[i] = nx; } rep(i,Q){ int t; cin >> t; if(t == 1){ int x; cin >> x; x--; char c; cin >> c; auto [nx,isnew] = getNext(pos[x], c); if(isnew){ lct.set(lct.at(nx), {1}); lct.link(lct.at(nx), lct.at(pos[x])); } else{ lct.set(lct.at(nx), { lct.get(lct.at(nx)).x + 1 }); } pos[x] = nx; } if(t == 2){ int x; cin >> x; x--; auto ans = lct.prod(lct.at(0), lct.at(pos[x])).x; cout << ans << '\n'; } } return 0; } struct ios_do_not_sync{ ios_do_not_sync(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); } } ios_do_not_sync_instance;