bzoj 3172 AC自动机
代码:
//建好AC自动机后就是fail的转移了,数量是从底向上转移的所以用一个队列记录下来节点顺序然后转移val数组即可。 #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN=1000009; int node[MAXN][30],f[MAXN],val[MAXN],tr[209],sz,qq[MAXN]; char s[MAXN]; int n; void init() { sz=0; memset(node[0],0,sizeof(node[0])); f[0]=val[0]=0; } void insert(char *s,int nu) { int len=strlen(s),rt=0; for(int i=0;i<len;i++){ int id=s[i]-'a'; if(!node[rt][id]){ node[rt][id]=++sz; memset(node[sz],0,sizeof(node[sz])); val[sz]=0; } rt=node[rt][id]; val[rt]++; } tr[nu]=rt; } void get_fail() { queue<int>q; int top=0; for(int i=0;i<26;i++){ int u=node[0][i]; if(u) { q.push(u);f[u]=0; } } while(!q.empty()){ int rt=q.front();q.pop();qq[++top]=rt; for(int i=0;i<26;i++){ int u=node[rt][i]; if(!u){ node[rt][i]=node[f[rt]][i]; continue; } q.push(u); f[u]=node[f[rt]][i]; } } for(int i=top;i>=1;i--) val[f[qq[i]]]+=val[qq[i]]; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s); insert(s,i); } get_fail(); for(int i=1;i<=n;i++) printf("%d\n",val[tr[i]]); return 0; }