BZOJ 3172

3172: [Tjoi2013]单词

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 3472  Solved: 1668
[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

HINT

AC自动机

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define N 1000005
 7 using namespace std;
 8 int pos[N],n;
 9 struct acm
10 {
11     int cnt;
12     int next[N][26],q[N],sum[N],fail[N];
13     char ch[N];
14     acm()
15     {
16         cnt=1;
17         for(int i=0;i<26;i++)next[0][i]=1;
18     }
19     void insert(int &pos)
20     {
21         int now=1;
22         scanf("%s",ch);
23         int len=strlen(ch);
24         for(int i=0;i<len;i++)
25         {
26             if(!next[now][ch[i]-'a'])next[now][ch[i]-'a']=++cnt;
27             now=next[now][ch[i]-'a'];
28             sum[now]++;
29         }
30         pos=now;
31     }
32     void buildfail()
33     {
34         int head=0,tail=1;
35         q[0]=1;fail[1]=0;
36         while(head!=tail)
37         {
38             int now=q[head++];
39             for(int i=0;i<26;i++)
40             {
41                 int v=next[now][i];
42                 if(!v)continue;
43                 int k=fail[now];
44                 while(!next[k][i])k=fail[k];
45                 fail[v]=next[k][i];
46                 q[tail++]=v;
47             }
48         }
49         for(int i=tail-1;i>=0;i--)
50             sum[fail[q[i]]]+=sum[q[i]];
51     }
52 }trie;
53 int main()
54 {
55     scanf("%d",&n);
56     for(int i=1;i<=n;i++)trie.insert(pos[i]);
57     trie.buildfail();
58     for(int i=1;i<=n;i++)printf("%d\n",trie.sum[pos[i]]);
59 //    system("pause");
60     return 0;
61 }
62         

这题bzoj上我都能排进rank前50??

posted @ 2017-02-26 01:22  hyf20010101  阅读(300)  评论(1编辑  收藏  举报