【HDU2896】病毒侵袭——ac自动机

网上很多代码都略显繁琐,看了一下yy dalao的代码感觉很好,但他懒得打题解(好吧我也是

以0为根节点的话,我把yy的一段代码删了改用fail[c]=x==0?0:ch[fail[x]][i];来实现特判,效果还不错!
也算是AC自动机的模版题吧,用了一个id数组来储藏每一个特征码的最后一个字符所在位置,再用vis来看网站源码中有哪条特征码(即哪条特征码的id被访问到)

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 char s[205],t[10005];
 5 int fail[100001],q[100002],ch[100002][130],val[100002],id[505],vis[100002];
 6 int sz=0,ans=0,n;
 7 void trie(int x)
 8 {
 9     int u=0,m=strlen(s);
10     for(int i=0;i<m;i++)
11     {
12         int c=s[i];
13         if(!ch[u][c])
14         ch[u][c]=++sz;    
15         u=ch[u][c];
16     }
17     id[x]=u;
18     val[u]++;
19 }
20 void makefail()
21 {
22     int head=0,tail=1;
23     q[1]=0;fail[0]=0;
24     while(head!=tail)
25     {
26         int x=q[++head];if(head>=100000)head=0;
27         for(int i=0;i<128;i++){
28             int c=ch[x][i];
29             if(!c){ch[x][i]=ch[fail[x]][i];continue;}
30             q[++tail]=c;if(tail>=100000)tail=0;
31             fail[c]=x==0?0:ch[fail[x]][i];
32         }
33     }
34 }
35 void ac(int x)
36 {
37     int f=0,k=0,len=strlen(t);
38     memset(vis,0,sizeof(vis));
39     for(int i=0;i<len;i++){
40         int u=t[i];
41         k=ch[k][u];
42         for(int j=k;j;j=fail[j]){if(val[j]){f=1;vis[j]=1;}}
43     }
44     if(!f)return;
45     ans++;printf("web %d:",x);
46     for(int i=1;i<=n;i++)
47         if(vis[id[i]])printf(" %d",i);
48     printf("
");
49 }
50 int main()
51 {
52     int m;
53     scanf("%d",&n);
54     for(int i=1;i<=n;i++){
55         scanf("%s",s);
56         trie(i);
57     }
58     makefail();
59     scanf("%d",&m);
60     for(int i=1;i<=m;i++)
61     {
62         scanf("%s",t);
63         ac(i);
64     }
65     printf("total: %d
",ans);
66     return 0;
67 }
hdu2896
原文地址:https://www.cnblogs.com/JKAI/p/6914583.html