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
这道题就是给定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 }