【bzoj3172】[Tjoi2013]单词

3172: [Tjoi2013]单词

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 3034  Solved: 1447
[Submit][Status][Discuss]

Description

某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。

Input

第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6

Output

输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。

Sample Input

3
a
aa
aaa

Sample Output

6
3
1

 

【题解】

很裸的AC自动机。

pos记录一下字符串结束的位置,每个结点初始权值都为1,结点的fail指针指向的点的权值要加上这个结点的权值。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<algorithm>
 8 using namespace std;
 9 #define MAXN 1000010
10 int n,cnt,v[MAXN],pos[MAXN],q[MAXN],fail[MAXN],tr[MAXN][27];
11 char ch[MAXN];
12 void insert(int &now)
13 {
14     now=0;
15     for(int i=1;i<=strlen(ch+1);i++)
16     {
17         if(!tr[now][ch[i]-'a']) tr[now][ch[i]-'a']=++cnt;
18         now=tr[now][ch[i]-'a'];
19         v[now]++;
20     }
21 }
22 void build()
23 {
24     int head=0,tail=0;
25     for(int i=0;i<26;i++)  if(tr[0][i])  q[++tail]=tr[0][i];
26     while(++head<=tail)
27     {
28         int x=q[head];
29         for(int i=0;i<26;i++)
30         {
31             int y=tr[x][i];
32             if(!y) continue;
33             q[++tail]=y;
34             int temp=fail[x];
35             while(temp&&!tr[temp][i])  temp=fail[temp];
36             fail[y]=tr[temp][i];
37         }
38     }
39     for(int i=tail;i;i--)  v[fail[q[i]]]+=v[q[i]];
40 }
41 int main()
42 {
43     //freopen("cin.in","r",stdin);
44     //freopen("cout.out","w",stdout);
45     scanf("%d",&n);
46     for(int i=1;i<=n;i++)  {scanf("%s",ch+1);  insert(pos[i]);}
47     build();
48     for(int i=1;i<=n;i++)  printf("%d\n",v[pos[i]]);
49     return 0;
50 }

 

posted @ 2016-10-26 20:17  chty  阅读(155)  评论(0编辑  收藏  举报