There \ (n-\) a query string \ (S_i \) , there is an initially empty set of character strings \ (T \) , followed with a \ (Q \) operations, each time a character string is added to the collection or given \ (x \) asked how many collection string contains \ (S_x \)
Solution
Consider \ (S_i \) establish ACAM, to build a \ (fail \) tree, a match point occurs, you need to modify it to the root of the chain, is asking a query point value
This requires split tree chain, we can look at the difference, so every change is a point of asking is a sub-tree and
So we determined \ (Fail \) the DFS tree sequence, a maintenance tree array, each modification, the input string is run on ACAM thrown, all the nodes on the matching \ (1 + \) , where the need open tag array, to prevent the same input string to the same node multiple \ (1 + \)
At each interrogation, to output \ (S_x \) subtree and to the corresponding subtree
It is clear that the above solution is wrong!
While we ensure that for each query string, we only played once labeled the same node, but the prefix and the results will still go back to repeat
So we need another way to solve this problem and path
On the basis of the above solution , considering all points labeled played out according to \ (DFS \) sequence ordering, adjacent nodes \ (LCA \) position \ (- 1 \) to
#include <bits/stdc++.h>
using namespace std;
const int N = 2000005;
int ar[N];
int lowbit(int t) {
return t & (-t);
}
void add(int i, int v) {
if(i==0) return;
for (; i < N; ar[i] += v, i += lowbit(i));
}
int sum(int i) {
int s = 0;
for (; i > 0; s += ar[i], i -= lowbit(i));
return s;
}
int sum(int p,int q) {
return sum(q)-sum(p-1);
}
int dfn[N],idfn[N],fin[N],dep[N],fa[N][21];
int lca(int p,int q) {
if(dep[p]<dep[q]) swap(p,q);
for(int i=20;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
for(int i=20;i>=0;--i) if(fa[p][i]-fa[q][i]) p=fa[p][i],q=fa[q][i];
if(p==q) return p;
else return fa[p][0];
}
struct ACA {
queue <int> q;
int c[N][26],val[N],fi[N],cnt,ans[1005];
void init() {
memset(c,0,sizeof c);
memset(val,0,sizeof val);
memset(fi,0,sizeof fi);
memset(ans,0,sizeof ans);
cnt=0;
}
int ins(char *str,int id) {
int len=strlen(str), p=0;
for(int i=0; i<len; i++) {
int v=str[i]-'a';
if(!c[p][v]) c[p][v]=++cnt;
p=c[p][v];
}
val[p]=id;
return p;
}
void build() {
for(int i=0; i<26; i++) if(c[0][i]) fi[c[0][i]]=0, q.push(c[0][i]);
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=0; i<26; i++)
if(c[u][i]) fi[c[u][i]]=c[fi[u]][i], q.push(c[u][i]);
else c[u][i]=c[fi[u]][i];
}
}
void query(char *s) {
set<int> st;
int len=strlen(s);
int p=0;
for(int i=0; i<len; i++) {
p=c[p][s[i]-'a'];
if(p&&st.find(dfn[p])==st.end()) {
st.insert(dfn[p]);
add(dfn[p],1);
}
}
vector <int> vec;
for(auto i=st.begin();i!=st.end();i++) vec.push_back(*i);
for(int i=1;i<vec.size();i++) {
add(dfn[lca(idfn[vec[i]],idfn[vec[i-1]])],-1);
}
}
} acam;
vector<int> g[N];
int n,q,endid[N],ind;
char str[N];
void dfs(int p) {
dfn[p]=++ind; idfn[ind]=p;
for(int q:g[p]) fa[q][0]=p, dep[q]=dep[p]+1, dfs(q);
fin[p]=ind;
}
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1; i<=n; i++) {
cin>>str;
endid[i]=acam.ins(str,i);
}
acam.build();
for(int i=1; i<=acam.cnt; i++) g[acam.fi[i]].push_back(i);
dfs(0);
for(int j=1;j<=20;j++) {
for(int i=1;i<=acam.cnt;i++) {
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
cin>>q;
for(int i=1; i<=q; i++) {
int t1,t2;
cin>>t1;
if(t1==1) {
cin>>str;
acam.query(str);
} else {
cin>>t2;
cout<<sum(dfn[endid[t2]],fin[endid[t2]])<<endl;
}
}
}