【USACO】AC自动机
Description
对,这就是裸的AC自动机。
要求:在规定时间内统计出模版字符串在文本中出现的次数。
Input
第一行:模版字符串的个数N。
第2->N+1行:N个字符串。(每个模版字符串的长度<=50)
第N+2行:一行很长的字符串。长的很。(使用AC自动机能在1s内计算出)
Output
共N行,每行输出一个模版及出现的次数。(之间有一个空格,按照输入顺序输出)
Sample Input
4
hers
her
his
she
shershisher
Sample Output
hers 1
her 2
his 1
she 2
Hint
所有字母均为小写
所给模版不会重复
模版题 贴代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 7 struct Lin 8 { 9 int next[27]; 10 int cnt,id; 11 }a[10001]; 12 char s[10000001]; 13 int fail[10001]; 14 int ans[10001]; 15 char o[10001][51]; 16 int num=0; 17 18 void work(int x) 19 { 20 scanf("%s",o[x]); 21 int ls=strlen(o[x]);int u; 22 int p=0; 23 for(int i=0;i<ls;i++) 24 { 25 u=o[x][i]-'a'; 26 if(a[p].next[u])p=a[p].next[u]; 27 else 28 { 29 a[p].next[u]=++num; 30 p=num; 31 } 32 } 33 a[p].cnt++; 34 a[p].id=x; 35 } 36 37 void getfail() 38 { 39 queue<int>q; 40 q.push(0); 41 int u,v,p; 42 while(!q.empty()) 43 { 44 u=q.front(); 45 q.pop(); 46 for(int i=0;i<26;i++) 47 { 48 v=a[u].next[i]; 49 if(!v)continue; 50 p=fail[u]; 51 while(p) 52 { 53 if(a[p].next[i]) 54 { 55 break; 56 } 57 p=fail[p]; 58 } 59 if(a[p].next[i] && a[p].next[i]!=v)fail[v]=a[p].next[i]; 60 q.push(v); 61 } 62 } 63 } 64 void getanswer() 65 { 66 scanf("%s",s); 67 int p=0;int ls=strlen(s);int u;int go; 68 for(int i=0;i<ls;i++) 69 { 70 u=s[i]-'a'; 71 while(!a[p].next[u] && p)p=fail[p]; 72 p=a[p].next[u]; 73 go=p; 74 while(go) 75 { 76 ans[a[go].id]+=a[go].cnt; 77 go=fail[go]; 78 } 79 } 80 return ; 81 } 82 83 int main() 84 { 85 int n; 86 scanf("%d",&n); 87 for(int i=1;i<=n;i++) 88 work(i); 89 getfail(); 90 getanswer(); 91 for(int i=1;i<=n;i++) 92 printf("%s %d\n",o[i],ans[i]); 93 return 0; 94 }