病毒侵袭
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 20378 Accepted Submission(s): 4977
Problem Description
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~
但 网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的 网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t 收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的 网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
但 网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小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码可见字符(不包括回车)。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
Output
依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
Sample Input
3
aaa
bbb
ccc
2
aaabbbccc
bbaacc
Sample Output
web 1: 1 2 3
total: 1
Source
题意:不解释。
题解:AC自动机,为每一个病毒标记一个ID,然后进行查询,两个坑点,一定要用gets()读入,next数组一定要开到128,可见字符是127个,我习惯性的减了个'a' runtime无数次。。。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int N = 10005; struct Node { Node *fail; Node *next[128]; int id; Node() { fail = NULL; id = 0; memset(next,NULL,sizeof(next)); } }; char T[1005]; char str[N]; int Rank[1005][10]; bool vis[1005]; void buildTrie(char *str,Node *root,int id) { Node *p = root,*q; int len = strlen(str); for(int i=0; i<len; i++) { int idx = str[i]; if(p->next[idx]==NULL) p->next[idx]=new Node(); p = p->next[idx]; } p->id = id; } void build_AC_automation(Node *root) { queue<Node*> q; root->fail = NULL; q.push(root); while(!q.empty()) { Node *p = NULL; Node *temp = q.front(); q.pop(); for(int i=0; i<128; i++) { if(temp->next[i]!=NULL) { if(temp==root) temp->next[i]->fail=root; else { p=temp->fail; while(p!=NULL) { if(p->next[i]!=NULL) { temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) temp->next[i]->fail=root; } q.push(temp->next[i]); } } } } int query(char *str,Node *root,int id) { int len = strlen(str); Node *p = root; int cnt = 0; memset(vis,false,sizeof(vis)); for(int i=0;i<len;i++){ int idx = str[i]; while(p->next[idx]==NULL&&p!=root) p = p->fail; p = p->next[idx]; p = (p==NULL)?root:p; Node * temp = p; while(temp!=root&&!vis[temp->id]){ if(temp->id!=0&&!vis[temp->id]&&cnt<=3){ vis[temp->id] = true; Rank[id][cnt++] = temp->id; } temp = temp->fail; } } return cnt; } int main() { Node *root = new Node(); int n; scanf("%d",&n); getchar(); int id = 1; while(n--){ gets(T); buildTrie(T,root,id); id++; } build_AC_automation(root); int m; scanf("%d",&m); getchar(); id = 1; int total = 0; while(m--){ gets(str); int ans = query(str,root,id); if(ans!=0&&ans<=3){ printf("web %d:",id); sort(Rank[id],Rank[id]+ans); for(int i=0;i<ans;i++){ printf(" %d",Rank[id][i]); } printf(" "); total++; } id++; } printf("total: %d ",total); return 0; }