HDU 3065 病毒侵袭持续中(AC自动机(每个模式串出现次数))
http://acm.hdu.edu.cn/showproblem.php?pid=3065
题意:
求每个模式串出现的次数。
思路:
不难,把模板修改一下即可。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 const int INF = 0x3f3f3f3f; 14 const int maxn=10000+5; 15 16 int n; 17 int num; 18 char str[1005][55]; 19 char s[2000005]; 20 int ans[1005]; 21 22 struct Trie 23 { 24 int son[30]; 25 int cnt; 26 int id; 27 int fail; 28 }t[1000*50+5]; 29 30 void init(int x) 31 { 32 t[x].cnt=t[x].fail=0; 33 memset(t[x].son,0,sizeof(t[x].son)); 34 } 35 36 void trie(char *s, int id) 37 { 38 int n=strlen(s); 39 int x=0; 40 for(int i=0;i<n;i++) 41 { 42 int c=s[i]-'A'+1; 43 if(!t[x].son[c]) 44 { 45 num++; 46 init(num); 47 t[x].son[c]=num; 48 } 49 x=t[x].son[c]; 50 } 51 t[x].cnt++; 52 t[x].id=id; 53 } 54 55 void buildAC() 56 { 57 queue<int> Q; 58 for(int i=1;i<=26;i++) if(t[0].son[i]) Q.push(t[0].son[i]); 59 while(!Q.empty()) 60 { 61 int x=Q.front(); Q.pop(); 62 int fail=t[x].fail; 63 for(int i=1;i<=26;i++) 64 { 65 int y=t[x].son[i]; 66 if(y) 67 { 68 t[y].fail=t[fail].son[i]; 69 Q.push(y); 70 } 71 else t[x].son[i]=t[fail].son[i]; 72 } 73 } 74 } 75 76 void query(char *s) 77 { 78 int n=strlen(s); 79 int x=0; 80 for(int i=0;i<n;i++) 81 { 82 if(!(s[i]>='A' && s[i]<='Z')) {x=0;continue;} 83 int c=s[i]-'A'+1; 84 while(x && !t[x].son[c]) x=t[x].fail; 85 x=t[x].son[c]; 86 int tmp=x; 87 while(tmp) //回到0就不需要再计数了 88 { 89 if(t[tmp].cnt!=0) ans[t[tmp].id]++; 90 tmp=t[tmp].fail; 91 } 92 } 93 } 94 95 int main() 96 { 97 //freopen("in.txt","r",stdin); 98 while(~scanf("%d",&n)) 99 { 100 num=0; 101 init(0); 102 scanf("%d",&n); 103 for(int i=1;i<=n;i++) 104 { 105 ans[i]=0; 106 scanf("%s",str[i]); 107 trie(str[i],i); 108 } 109 buildAC(); 110 scanf("%s",s); 111 query(s); 112 for(int i=1;i<=n;i++) 113 { 114 if(ans[i]) printf("%s: %d\n",str[i],ans[i]); 115 } 116 } 117 return 0; 118 }