3172: [Tjoi2013]单词

Description

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

Input

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

Output

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

Sample Input

3
a
aa
aaa

Sample Output

6
3
1
 
 
这道题就是给定n个字符串,询问每个字符串在其他的字符串中出现了几次。。。
很容想到可以用AC自动机来做,我们对于每个字符串的每个节点都沿着fail指针走,每走到一个节点就把这个节点++;
但是这样做会超时。。。
引入fail树,fail树就是把AC自动机的fail指针反向,就构成了一棵树,我们在树上走就不会T了。。。。
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #include<string>
 8 #include<map>
 9 #include<queue>
10 #include<vector>
11 #include<set>
12 #define inf 1000000000
13 #define maxn 1000000+5
14 #define maxm 26
15 #define eps 1e-10
16 #define ll long long
17 #define for0(i,n) for(int i=0;i<=(n);i++)
18 #define for1(i,n) for(int i=1;i<=(n);i++)
19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
22 using namespace std;
23 int read(){
24     int x=0,f=1;char ch=getchar();
25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 int n,pos[maxn];
30 struct acm{
31     int tot;
32     int next[maxn][maxm],sum[maxn],fail[maxn],q[maxn];
33     char ch[maxn];
34     acm(){
35         tot=1;
36         for0(i,25)next[0][i]=1;
37     }
38     void insert(int &pos){
39         int now=1;
40         scanf("%s",ch);
41         int n=strlen(ch);
42         for0(i,n-1){
43             if(!next[now][ch[i]-'a'])next[now][ch[i]-'a']=++tot;
44             now=next[now][ch[i]-'a'];
45             sum[now]++;
46         }
47         pos=now;
48     }
49     void build(){
50         int head=0,tail=1;
51         q[0]=1;fail[1]=0;
52         while(head!=tail){
53             int now=q[head];head++;
54             for0(i,25){
55                 int v=next[now][i];
56                 if(!v)continue;
57                 int k=fail[now];
58                 while(!next[k][i])k=fail[k];
59                 fail[v]=next[k][i];
60                 q[tail++]=v;
61             }
62         }
63         for(int i=tail-1;i>=0;i--)
64             sum[fail[q[i]]]+=sum[q[i]];
65     }
66 }acm;
67 int main(){
68     //freopen("input.txt","r",stdin);
69     //freopen("output.txt","w",stdout);
70     n=read();
71     for1(i,n)
72         acm.insert(pos[i]);
73     acm.build();
74     for1(i,n)
75         printf("%d\n",acm.sum[pos[i]]);
76     return 0;
77 }
View Code

 

posted @ 2016-06-02 08:36  HTWX  阅读(120)  评论(0编辑  收藏  举报