程序员人生 网站导航

HDU 2896 病毒侵袭 (AC自动机模板)

栏目:php教程时间:2015-04-08 08:33:32

病毒侵袭

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13063    Accepted Submission(s): 3378


Problem Description
当太阳的光辉逐步被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋――我们能在有生之年看到500年1遇的世界奇观,那是多么幸福的事儿啊~~
但网路上总有那末些网站,开始借着民众的好奇心,打着介绍日蚀的旗号,大肆传播病毒。小t不幸成为受害者之1。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。固然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t搜集了好多病毒的特点码,又搜集了1批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底搜集了多少带病毒的网站。这时候候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
 

Input
第1行,1个整数N(1<=N<=500),表示病毒特点码的个数。
接下来N行,每行表示1个病毒特点码,特点码字符串长度在20―200之间。
每一个病毒都有1个编号,依此为1―N。
不同编号的病毒特点码不会相同。
在这以后1行,有1个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示1个网站源码,源码字符串长度在7000―10000之间。
每一个网站都有1个编号,依此为1―M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
 

Output
顺次按以下格式输出按网站编号从小到大输出,带病毒的网站编号和包括病毒编号,每行1个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有1个空格,病毒编号按从小到大排列,两个病毒编号之间用1个空格隔开,如果1个网站包括病毒,病毒数不会超过3个。
最后1行输出统计信息,以下格式
total: 带病毒网站数
冒号后有1个空格。
 

Sample Input
3 aaa bbb ccc 2 aaabbbccc bbaacc
 

Sample Output
web 1: 1 2 3 total: 1
 

Source
2009 Multi-University Training Contest 10 - Host by NIT

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896

题目分析:给病毒建立trie树,跑1下ac自动机,记录1下序号,注意可见的ASCII码从33到128

#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; int const MAX = 1e4 + 5; int ans[MAX], num; char word[205], text[MAX]; struct node { int id; bool end; node *next[96]; node *fail; node() { id = 0; end = false; memset(next, NULL, sizeof(next)); fail = NULL; } }; void Insert(node *p, char *s, int id) { for(int i = 0; s[i] != ''; i++) { int idx = s[i] - 32; if(p -> next[idx] == NULL) p -> next[idx] = new node(); p = p -> next[idx]; } p -> end = true; p -> id = id; } void AC_Automation(node *root) { queue <node*> q; q.push(root); while(!q.empty()) { node *p = q.front(); q.pop(); for(int i = 0; i < 96; i++) { if(p -> next[i]) { if(p == root) p -> next[i] -> fail = root; else p -> next[i] -> fail = p -> fail -> next[i]; q.push(p -> next[i]); } else { if(p == root) p -> next[i] = root; else p -> next[i] = p -> fail -> next[i]; } } } } bool Query(node *root) { bool flag = false; num = 0; int cnt = 0, len = strlen(text); node *p = root; for(int i = 0; i < len; i++) { if(num == 3) break; int idx = text[i] - 32; while(!p -> next[idx] && p != root) p = p -> fail; p = p -> next[idx]; if(!p) { p = root; continue; } node *tmp = p; while(tmp != root) { if(tmp -> end) { flag = true; ans[num++] = tmp -> id; break; } tmp = tmp -> fail; } } return flag; } int main() { int n, m, tot = 0; scanf("%d", &n); getchar(); node *root = new node(); for(int i = 1; i <= n; i++) { gets(word); Insert(root, word, i); } AC_Automation(root); scanf("%d", &m); getchar(); for(int i = 1; i <= m; i++) { gets(text); if(Query(root)) { tot++; printf("web %d:", i); sort(ans, ans + num); for(int j = 0; j < num; j++) printf(" %d", ans[j]); printf(" "); } } printf("total: %d ", tot); }


 

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐