某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 int n; 9 int num; 10 int tot; 11 int cnt; 12 int g[300]; 13 char s[1000010]; 14 int to[1000010]; 15 int sum[1000010]; 16 int fail[1000010]; 17 int next[1000010]; 18 int head[1000010]; 19 int a[1000010][26]; 20 void add(int x,int y) 21 { 22 tot++; 23 next[tot]=head[x]; 24 head[x]=tot; 25 to[tot]=y; 26 } 27 void build(char *s) 28 { 29 int now=0; 30 int len=strlen(s); 31 for(int i=0;i<len;i++) 32 { 33 if(!a[now][s[i]-‘a‘]) 34 { 35 a[now][s[i]-‘a‘]=++cnt; 36 } 37 now=a[now][s[i]-‘a‘]; 38 sum[now]++; 39 } 40 g[++num]=now; 41 } 42 void getfail() 43 { 44 queue<int>q; 45 for(int i=0;i<26;i++) 46 { 47 if(a[0][i]) 48 { 49 fail[a[0][i]]=0; 50 q.push(a[0][i]); 51 } 52 } 53 while(!q.empty()) 54 { 55 int now=q.front(); 56 q.pop(); 57 for(int i=0;i<26;i++) 58 { 59 if(a[now][i]) 60 { 61 fail[a[now][i]]=a[fail[now]][i]; 62 q.push(a[now][i]); 63 } 64 else 65 { 66 a[now][i]=a[fail[now]][i]; 67 } 68 } 69 } 70 } 71 void dfs(int x) 72 { 73 for(int i=head[x];i;i=next[i]) 74 { 75 dfs(to[i]); 76 sum[x]+=sum[to[i]]; 77 } 78 return ; 79 } 80 int main() 81 { 82 scanf("%d",&n); 83 for(int i=1;i<=n;i++) 84 { 85 scanf("%s",s); 86 build(s); 87 } 88 getfail(); 89 for(int i=1;i<=cnt;i++) 90 { 91 add(fail[i],i); 92 } 93 dfs(0); 94 for(int i=1;i<=n;i++) 95 { 96 printf("%d\n",sum[g[i]]); 97 } 98 }
BZOJ3172[Tjoi2013]单词——AC自动机(fail树)
原文:https://www.cnblogs.com/Khada-Jhin/p/9164559.html