Keywords Search
OJ题号:HDU2222
思路:
AC自动机。
同一个模板串只能算一遍,所以每找到一个模板串就要吧当前串的cnt变成0,避免重复计算。注意可能会有相同的模板串,所以要用cnt来保存出现的次数。
第一次做AC自动机,主要参考刘汝佳的训练指南和网上一个题解
http://blog.csdn.net/morgan_xww/article/details/7834338 1 #define maxnode 500000 2 #define sigma_size 26 3 #include<queue> 4 #include<cstdio> 5 #include<cstring> 6 using namespace std; 7 struct AC { 8 int ch[maxnode][sigma_size]; 9 int val[maxnode],last[maxnode],f[maxnode],cnt[maxnode]; 10 int sz; 11 int idx(char c) { 12 return c-'a'; 13 } 14 void reset() { 15 memset(ch[0],0,sizeof(ch[0])); 16 sz=1; 17 } 18 void insert(char *s) { 19 int u=0,n=strlen(s); 20 for(int i=0;i<n;i++) { 21 int c=idx(s[i]); 22 if(!ch[u][c]) { 23 memset(ch[sz],0,sizeof(ch[sz])); 24 cnt[sz]=val[sz]=0; 25 ch[u][c]=sz++; 26 } 27 u=ch[u][c]; 28 } 29 val[u]=1; 30 cnt[u]++; 31 } 32 void getFail() { 33 queue<int> q; 34 f[0]=0; 35 //Initialize 36 for(int c=0;c<sigma_size;c++) { 37 int u=ch[0][c]; 38 if(u) { 39 f[u]=0; 40 q.push(u); 41 last[u]=0; 42 } 43 } 44 //calc last in BFS way 45 while(!q.empty()) { 46 int r=q.front(); 47 q.pop(); 48 for(int c=0;c<sigma_size;c++) { 49 int u=ch[r][c]; 50 if(!u) { 51 ch[r][c]=ch[f[r]][c]; 52 continue; 53 } 54 q.push(u); 55 int v=f[r]; 56 while(v&&!ch[v][c]) v=f[v]; 57 f[u]=ch[v][c]; 58 last[u]=val[f[u]]?f[u]:last[f[u]]; 59 } 60 } 61 } 62 int find(char *t) { 63 int n=strlen(t),j=0,ans=0; 64 for(int i=0;i<n;i++) { 65 int c=idx(t[i]); 66 j=ch[j][c]; 67 int u=j; 68 while(u) { 69 ans+=cnt[u]; 70 cnt[u]=0; 71 u=f[u]; 72 } 73 } 74 return ans; 75 } 76 }; 77 AC ac; 78 int main() { 79 int t; 80 scanf("%d",&t); 81 while(t--) { 82 int n; 83 scanf("%d",&n); 84 ac.reset(); 85 while(n--) { 86 char s[1000001]; 87 scanf("%s",s); 88 ac.insert(s); 89 } 90 ac.getFail(); 91 char s[51]; 92 scanf("%s",s); 93 printf("%d\n",ac.find(s)); 94 } 95 return 0; 96 }
注:本随笔整理自QQ空间旧文。发布时间为2017年3月15日。