hdu 2896 病毒入侵 AC自动机
来源:互联网 发布:fastboot刷zip软件 编辑:程序博客网 时间:2024/06/16 14:42
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到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 自动机模板吧 其实就改了个标记而已。。甚至标记都不用改。
#include <stdio.h>#include <stdlib.h>#include <algorithm>#include <vector>using namespace std;#define M 10010struct node{ int next[128]; int fail; int sign;}t[M<<4];int q[M<<4],head=0,tail=1;int r[550],H=0,f[5],k,n,L=0;char str[220],s[M];vector<int> v;void Insert(char *a,int tot){ int i=0,p=0,j,x; while(a[i]) { x=t[p].next[a[i]]; if(x<0) { t[p].next[a[i]]=x=++L; for(j=0;j<128;j++) t[x].next[j]=-1; t[x].fail=-1;t[x].sign=0; } p=x; i++; } t[p].sign=tot;}void build_ACauto()//更新失配指针{ int i,p,x,y; q[0]=0; while(head<tail){ x=q[head++]; for(i=0;i<128;i++){ y=t[x].next[i]; if(y>=0){ if(x){ p=t[x].fail; while(p>=0){ if(t[p].next[i]>=0){ t[y].fail=t[p].next[i]; break; } p=t[p].fail; } if(p<0)t[y].fail=0; } else t[y].fail=0; q[tail++]=y; } } }}void ACauto()//启动AC自动机查找病毒串{ int i=0,p=0,x; while(s[i]){ while(t[p].next[s[i]]<0&&p)p=t[p].fail; p=t[p].next[s[i]]; if(p<0)p=0; x=p; while(x){ if(t[x].sign>0) v.push_back(t[x].sign); x=t[x].fail; } i++; } //由于查找过程中将查过的点赋为H,会影响下个网站的搜索 //所以此处应将病毒串尾还原为其编号 // for(i=1;i<=n;i++)t[r[i]].sign=i;}int main(){ int i,j,m,sum=0; scanf("%d",&n); t[0].fail=-1;t[0].sign=0; for(i=0;i<128;i++)t[0].next[i]=-1; for(i=1;i<=n;i++){ scanf("%s",str); Insert(str,i); } build_ACauto(); scanf("%d",&m); for(i=1;i<=m;i++){ v.clear(); scanf("%s",s); ACauto(); if(!v.size())continue; printf("web %d:",i); sort(v.begin(),v.end()); int kk=0; printf(" %d",v[0] ); for(j=1;j<v.size()&&kk<3;j++) { if(v[j]!=v[j-1]) printf(" %d",v[j]),kk++; } puts(""); sum++;//累加病毒网站数 } printf("total: %d\n",sum); return 0;}
新板子写法
#include <bits/stdc++.h>using namespace std;const int maxn=200010;const int maxm=200010;const int SIGMA_SIZE=128;int n;vector<int> v;struct AC{ int ch[maxm][128]; int val[maxm]; int fail[maxm],last[maxm]; int sz; void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;} int idx(char x){return x;} void insert(char *s,int id) { int u=0; int n=strlen(s); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=id; } void getfail() { queue<int> q; fail[0]=0; int u=0; for(int i=0;i<SIGMA_SIZE;i++) { u=ch[0][i]; if(u){q.push(u);fail[u]=0;last[u]=0;} } while(!q.empty()) { int r=q.front();q.pop(); for(int i=0;i<SIGMA_SIZE;i++) { u=ch[r][i]; if(!u){ch[r][i]=ch[fail[r]][i];continue;} q.push(u); int v=fail[r]; while(v&&!ch[v][i])v=fail[v]; fail[u]=ch[v][i]; last[u]=val[fail[u]]?fail[u]:last[fail[u]]; } } } int find(char *s) { int u=0,cnt=0; for(int i=0;s[i];i++) { int c=idx(s[i]); u=ch[u][c]; int temp=0;//必须赋初值为0,表示如果下面两个判断都不成立的时候while可以正常执行 if(val[u]) temp=u; else if(last[u]) temp=last[u]; while(temp) { if(val[temp]>0) v.push_back(val[temp]); temp=last[temp]; } } return cnt; }}tree;char str[220],s[10010];int main(){ int sum=0; tree.clear(); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",str); tree.insert(str,i); } tree.getfail(); int m; scanf("%d",&m); for(int i=1;i<=m;i++){ v.clear(); scanf("%s",s); tree.find(s); if(!v.size())continue; printf("web %d:",i); sort(v.begin(),v.end()); int kk=0; printf(" %d",v[0] ); for(int j=1;j<v.size()&&kk<3;j++) { if(v[j]!=v[j-1]) printf(" %d",v[j]),kk++; } puts(""); sum++;//累加病毒网站数 } printf("total: %d\n",sum ); return 0;}
- HDU 2896 病毒入侵 AC自动机
- hdu 2896 病毒入侵 AC自动机
- hdu 2896 病毒入侵 ac自动机入门 附加一组数据
- HDU 2896 病毒入侵 AC自动机 多模式串匹配
- HDU 2896 病毒侵袭 (AC自动机)
- hdu 2896 病毒侵袭 //AC自动机
- HDU 2896:病毒侵袭(AC自动机)
- hdu 2896 病毒侵袭 AC自动机
- HDU 2896 病毒侵袭(AC自动机)
- hdu 2896 病毒侵袭 AC自动机基础
- HDU 2896 病毒侵袭 AC自动机
- hdu 2896 病毒侵袭 -- AC自动机
- hdu 2896 病毒侵袭 (AC自动机)
- HDU 2896 病毒侵袭(AC 自动机)
- HDU 2896 病毒侵袭 (AC自动机)
- HDU 2896 病毒侵袭 【AC自动机】
- hdu 2896 病毒侵袭 AC自动机
- [HDU 2896]病毒侵袭[AC自动机]
- Codeforces Round #374 (Div. 2) C. Journey —— DP
- GITC 2017全球互联网技术大会 上海站早鸟票报名
- iOS自定义控件教程(二)关于响应链的那些事
- 南阳理工oj-5 Binary String Matching
- 大数据挖掘的本质和意义
- hdu 2896 病毒入侵 AC自动机
- 值栈
- MTK平台SD热插拔相关设置以及问题解决
- iOS自定义控件教程(三)UIView动画入门
- 23种设计模式之工厂方法模式
- linux多文件,多目录的嵌套编译
- iOS自定义控件教程(四)UIControl - 幕后的英雄
- 数据库中TIMESTAMP , DATE 和 DATETIME
- LeetCode_91、120两题(动态规划)