https://www.lydsy.com/JudgeOnline/problem.php?id=3172php
構建AC自動機spa
在fail樹上,點i的子樹大小 表示trie樹上根節點到i構成的單詞 是 多少個(子)串的子串code
#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]]); }