【hdu3065-病毒侵袭持续中】AC自动机

题意:给定一些只含大写字母的病毒串,再给一个文本串,问文本串中每个病毒串各出现了多少次。

题解:

就是用AC自动机,在每个节点末尾有个id记录是哪个单词的末尾,然后如果同时是多个单词的末尾就用一个next数组链状记录当前id的下一个值。
多组数据坑死人。坑死人。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<queue>
  6 using namespace std;
  7 
  8 const int N=50010,S=2000010,A=26;
  9 int n,num,cnt[N],nt[N],fir[N],sum[N];
 10 char ss[N][65],s[S];
 11 queue<int> q;
 12 struct node{
 13     int id,fail,son[30];
 14 }a[N];
 15 
 16 void clear(int x)
 17 {
 18     a[x].id=a[x].fail=0;
 19     memset(a[x].son,0,sizeof(a[x].son));
 20 }
 21 
 22 void trie(char *c,int id)
 23 {
 24     int x=0,l=strlen(c);
 25     for(int i=0;i<l;i++)
 26     {
 27         int ind=c[i]-'A'+1;
 28         if(!a[x].son[ind])
 29         {
 30             num++;
 31             clear(num);
 32             a[x].son[ind]=num;
 33         }
 34         x=a[x].son[ind];
 35     }
 36     if(!a[x].id) a[x].id=id,fir[x]=id;
 37     else nt[id]=a[x].id,a[x].id=id;
 38 }
 39 
 40 void buildAC()
 41 {
 42     while(!q.empty()) q.pop();
 43     for(int i=1;i<=A;i++)
 44         if(a[0].son[i]) q.push(a[0].son[i]);
 45     while(!q.empty())
 46     {
 47         int x=q.front();q.pop();
 48         int fail=a[x].fail;
 49         for(int i=1;i<=A;i++)
 50         {
 51             if(a[x].son[i])
 52             {
 53                 int y=a[x].son[i],z=a[fail].son[i];
 54                 a[y].fail=z;                
 55                 if(fir[y]) nt[fir[y]]=a[z].id;
 56                 else a[y].id=a[z].id;
 57                 q.push(y);
 58             }
 59             else a[x].son[i]=a[fail].son[i];
 60         }
 61     }
 62 }
 63 
 64 void find(char *c)
 65 {
 66     int x=0,l=strlen(c);
 67     for(int i=0;i<l;i++)
 68     {
 69         if(!(c[i]>='A' && c[i]<='Z')) {x=0;continue;}
 70         int ind=c[i]-'A'+1;
 71         x=a[x].son[ind];
 72         int p=a[x].id;
 73         while(p)
 74         {
 75             sum[p]++;
 76             p=nt[p];
 77         }
 78     }
 79 }
 80 
 81 int main()
 82 {
 83     freopen("a.in","r",stdin);
 84     freopen("a.out","w",stdout);
 85     while(scanf("%d",&n)!=EOF)
 86     {
 87         num=0;
 88         clear(0);
 89         memset(nt,0,sizeof(nt));
 90         memset(fir,0,sizeof(fir));
 91         memset(sum,0,sizeof(sum));
 92         scanf("%d",&n);
 93         for(int i=1;i<=n;i++)
 94         {
 95             scanf("%s",ss[i]);
 96             trie(ss[i],i);
 97         }
 98         buildAC();
 99         scanf("%s",s);
100         find(s);
101         for(int i=1;i<=n;i++) 
102             if(sum[i]) printf("%s: %d\n",ss[i],sum[i]);    
103     }
104 
105     return 0;
106 }

 

posted @ 2016-07-14 09:20  拦路雨偏似雪花  阅读(132)  评论(0编辑  收藏  举报