BZOJ 3172: [Tjoi2013]单词 AC自动机
3172: [Tjoi2013]单词
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
3
a
aa
aaa
a
aa
aaa
Sample Output
6
3
1
3
1
HINT
入门
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int N=1e6+10,mod=1e9+7,inf=2e9+10; int nex[N][27],head,tail,pos[N],cnt = 1,fail[N],sum[N],q[N],n; char a[N]; void insert(char *s,int &x) { int now = 1, len = strlen(s); for(int i = 0; i < len; ++i) { int index = s[i] - 'a'; if(!nex[now][index]) nex[now][index] = ++cnt; now = nex[now][index]; sum[now]++; } x = now; } void build_fail() { head = 0,tail = 0; q[tail++] = 1; fail[1] = 0; while(head != tail) { int now = q[head++]; for(int i = 0; i < 26; ++i) { if(!nex[now][i]) continue; int p = fail[now]; while(!nex[p][i]) p = fail[p]; fail[nex[now][i]] = nex[p][i]; q[tail++] = nex[now][i]; } } } int main() { for(int i = 0; i < 26; ++i) nex[0][i] = 1; scanf("%d",&n); for(int i = 1; i <= n; ++i) { scanf("%s",a); insert(a,pos[i]); }//cout<<1<<endl; build_fail(); for(int i = tail-1; i >=0; --i) sum[fail[q[i]]] += sum[q[i]]; for(int i = 1; i <= n; ++i) cout<<sum[pos[i]]<<endl; return 0; }