首页 > 代码库 > 【HDU2896】病毒侵袭 AC自动机
【HDU2896】病毒侵袭 AC自动机
【HDU2896】病毒侵袭
Problem Description
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~
但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
Input
第一行,一个整数N(1<=N<=500),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
Output
依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
Sample Input
3
aaa
bbb
ccc
2
aaabbbccc
bbaacc
Sample Output
web 1: 1 2 3
total: 1
题解:AC自动机,注意字符种类有128种,输出的时候还要处理一下。
竟然因为最后没输出回车而PE了半天~
#include <cstdio> #include <cstring> #include <queue> #include <iostream> #include <algorithm> using namespace std; struct node { int fail,num,ch[128]; }p[100010]; struct virus { char w[210]; int vis; }v[510]; int n,m,tot,len,sum; int ans[510]; char str[10010]; queue <int> q; bool cmp(int a,int b) { if(v[a].vis!=v[b].vis) return v[a].vis>v[b].vis; return a<b; } void build() { int i,u,t; q.push(1); while(!q.empty()) { u=q.front(),q.pop(); for(i=0;i<128;i++) { if(!p[u].ch[i]) continue; q.push(p[u].ch[i]); if(u==1) { p[p[u].ch[i]].fail=1; continue; } t=p[u].fail; while(!p[t].ch[i]&&t) t=p[t].fail; if(t) p[p[u].ch[i]].fail=p[t].ch[i]; else p[p[u].ch[i]].fail=1; } } } int main() { scanf("%d",&n); int i,j,k,u,t,flag; tot=1; for(i=1;i<=n;i++) { scanf("%s",v[i].w); k=strlen(v[i].w); t=1; for(j=0;j<k;j++) { if(!p[t].ch[v[i].w[j]]) p[t].ch[v[i].w[j]]=++tot; t=p[t].ch[v[i].w[j]]; } p[t].num=i; } build(); scanf("%d",&m); for(i=1;i<=n;i++) ans[i]=i; //先把1-n的病毒编号记下来,然后每次输出的时候将编号排序一遍 for(k=1;k<=m;k++) { scanf("%s",str); len=strlen(str); u=1; flag=0; for(i=1;i<=n;i++) v[i].vis=0; for(i=0;i<len;i++) { while(!p[u].ch[str[i]]&&u) u=p[u].fail; u=p[u].ch[str[i]]; t=u=u>0?u:1; while(t!=1) { if(p[t].num) { if(v[p[t].num].vis) break; v[p[t].num].vis=1,flag=1; } t=p[t].fail; } } if(!flag) continue; sum++; sort(ans+1,ans+n+1,cmp); printf("web %d:",k); for(j=1;j<=n&&v[ans[j]].vis;j++) printf(" %d",ans[j]); printf("\n"); } printf("total: %d\n",sum); return 0; }
【HDU2896】病毒侵袭 AC自动机