bzoj3172: [Tjoi2013]单词(AC自动机)
https://www.lydsy.com/JudgeOnline/problem.php?id=3172
构建AC自动机
在fail树上,点i的子树大小 表示trie树上根节点到i构成的单词 是 多少个(子)串的子串
#include<queue> #include<cstdio> #include<cstring> using namespace std; #define N 2000001 using namespace std; int pos[201]; int tr[N][26],id=1; int f[N],ans[N]; char s[1000001]; queue<int>q; int d[N],cnt; void insert(int &pos) { int now=1,len=strlen(s); int x; for(int i=0;i<len;++i) { x=s[i]-'a'; if(!tr[now][x]) tr[now][x]=++id; now=tr[now][x]; ans[now]++; } pos=now; } void get_fail() { for(int i=0;i<26;++i) tr[0][i]=1; q.push(1); int now,j; while(!q.empty()) { now=q.front(); d[++cnt]=now; q.pop(); for(int i=0;i<26;++i) if(!tr[now][i]) tr[now][i]=tr[f[now]][i]; else { q.push(tr[now][i]); j=f[now]; f[tr[now][i]]=tr[j][i]; } } } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%s",s); insert(pos[i]); } get_fail(); for(int i=cnt;i;--i) ans[f[d[i]]]+=ans[d[i]]; for(int i=1;i<=n;++i) printf("%d\n",ans[pos[i]]); }