hdu3065

题意:给出n个病毒串(模式串),再给出一个待匹配串,问每种模式串在其中出现了几次,0次不输出

也是将AC自动机的模板稍微修改了一下,由于每个模式串都不同,所以直接用cnt数组记录结点代表的模式串的标号,在匹配串时计数就可以了

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<queue>
 4 using namespace std;
 5 const int maxm=1010*55;
 6 
 7 char s[2000000+50],word[1010][55];
 8 int c;
 9 int vis[1010];
10 int nxt[maxm][128-30],cnt[maxm],fail[maxm],size;
11 
12 int newnode(){
13     memset(nxt[size],0,sizeof(nxt[size]));
14     fail[size]=cnt[size]=0;
15     return size++;
16 }
17 
18 void insert(char s[],int k){
19     int i,p=0;
20     for(i=0;s[i];i++){
21         int &x=nxt[p][s[i]-30];
22         p=x?x:x=newnode();
23     }
24     cnt[p]=k;
25 }
26 
27 void makenxt(){
28     int i;
29     queue<int>q;
30     q.push(0);
31     while(!q.empty()){
32         int u=q.front();
33         q.pop();
34         for(i=0;i<128-30;i++){
35             int v=nxt[u][i];
36             if(v==0)nxt[u][i]=nxt[fail[u]][i];
37             else q.push(v);
38             if(u&&v){
39                 fail[v]=nxt[fail[u]][i];
40             }
41         }
42     }
43 }
44 
45 void query(char s[]){
46     int d=0;
47     for(int i=0;s[i];i++){
48         d=nxt[d][s[i]-30];
49         int tmp=d;
50         while(tmp!=0){
51             vis[cnt[tmp]]++;
52             tmp=fail[tmp];
53         }
54     }
55 }
56 
57 int main(){
58     int n;
59     while(scanf("%d",&n)!=EOF){
60         size=0,newnode();
61         int i;
62         memset(cnt,0,sizeof(cnt));
63         memset(vis,0,sizeof(vis));
64         for(i=1;i<=n;i++){
65             scanf("%s",word[i]);
66             insert(word[i],i);
67         }
68         makenxt();
69         scanf("%s",s);
70         query(s);
71         for(i=1;i<=n;i++){
72             if(vis[i])printf("%s: %d\n",word[i],vis[i]);
73         }
74     }
75     return 0;
76 }
hdu3065