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
直接构造trie和AC自动机(fail树)
然后把文章拼出来,然后在AC自动机上,分别统计每个单词的出现次数
但这个方法很慢
实际上可以用前缀和思想,从fail树从下往上累加,省去了最慢的查询
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int N=1e6+205; 9 char s[N]; 10 int Q[N]; 11 int val[N],ch[N][28],size,f[N],n,mp[205],cnt[N]; 12 void insert(int len,int id) 13 {int i; 14 int now=0; 15 for (i=0;i<len;i++) 16 { 17 if (ch[now][s[i]-'a']==0) ch[now][s[i]-'a']=++size; 18 now=ch[now][s[i]-'a']; 19 cnt[now]++; 20 } 21 mp[id]=now; 22 } 23 void AC_build() 24 {int i,h,t; 25 h=0;t=0; 26 for (i=0;i<26;i++) 27 if (ch[0][i]) f[ch[0][i]]=0,Q[++t]=ch[0][i]; 28 while (h<t) 29 { 30 h++; 31 int u=Q[h]; 32 for (i=0;i<26;i++) 33 { 34 if (ch[u][i]) 35 { 36 f[ch[u][i]]=ch[f[u]][i];Q[++t]=ch[u][i]; 37 } 38 else ch[u][i]=ch[f[u]][i]; 39 } 40 } 41 for (i=t;i>=1;i--) 42 cnt[f[Q[i]]]+=cnt[Q[i]]; 43 } 44 int main() 45 {int i,len,j; 46 cin>>n; 47 for (i=1;i<=n;i++) 48 { 49 scanf("%s",s); 50 len=strlen(s); 51 insert(len,i); 52 } 53 AC_build(); 54 for (i=1;i<=n;i++) 55 printf("%d ",cnt[mp[i]]); 56 }
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 queue<int>Q; 9 const int N=1e6+205; 10 char T[N],s[N]; 11 int ans[205],val[N],ch[N][28],size,f[N],cnt,n,mp[205]; 12 void insert(int len,int id) 13 {int i; 14 int now=0; 15 for (i=0;i<len;i++) 16 { 17 if (ch[now][s[i]-'a']==0) ch[now][s[i]-'a']=++size; 18 now=ch[now][s[i]-'a']; 19 } 20 if (val[now]==0) 21 val[now]=id,mp[id]=id; 22 else mp[id]=val[now]; 23 } 24 void AC_build() 25 {int i; 26 for (i=0;i<27;i++) 27 if (ch[0][i]) f[ch[0][i]]=0,Q.push(ch[0][i]); 28 while (Q.empty()==0) 29 { 30 int u=Q.front(); 31 Q.pop(); 32 for (i=0;i<27;i++) 33 { 34 if (ch[u][i]) f[ch[u][i]]=ch[f[u]][i],Q.push(ch[u][i]); 35 else ch[u][i]=ch[f[u]][i]; 36 } 37 } 38 } 39 void query() 40 {int i,j; 41 int now=0,len=strlen(T); 42 for (i=0;i<len;i++) 43 { 44 now=ch[now][T[i]-'a']; 45 for (j=now;j;j=f[j]) 46 if (val[j]) 47 ans[val[j]]++; 48 //cout<<i<<' '<<val[j]<<endl; 49 } 50 } 51 int main() 52 {int i,len,j; 53 cin>>n; 54 cnt=-1; 55 for (i=1;i<=n;i++) 56 { 57 scanf("%s",s); 58 len=strlen(s); 59 insert(len,i); 60 T[++cnt]='a'+26; 61 for (j=0;j<len;j++) 62 T[++cnt]=s[j]; 63 //T[++cnt]='a'+26; 64 } 65 AC_build(); 66 query(); 67 for (i=1;i<=n;i++) 68 printf("%d ",ans[mp[i]]); 69 }