HDU2896AC自动机模板
来源:互联网 发布:淘宝网床上用品 编辑:程序博客网 时间:2024/05/18 12:37
病毒侵袭
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10281 Accepted Submission(s): 2670
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
3aaabbbccc2aaabbbcccbbaacc
Sample Output
web 1: 1 2 3total: 1
Source
2009 Multi-University Training Contest 10 - Host by NIT
关于
shr
h
下面的版建树是这样的
黑线为字典树转移,红线为失败指针,蓝线为优化指针
整合版,加入节点转移优化,当一个节点为空时直接转移至fail节点
#define DeBUG#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <string>#include <set>#include <sstream>#include <map>#include <list>#include <bitset>using namespace std ;#define zero {0}#define INF 0x3f3f3f3f#define EPS 1e-6typedef long long LL;const double PI = acos(-1.0);//#pragma comment(linker, "/STACK:102400000,102400000")inline int sgn(double x){ return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}#define N 100005#define cha 128#define TRUE true#define FALSE false#define Type intbool used[510];struct Trie{ int next[N][cha]; int fail[N]; Type end[N];//用于存放目标节点数据 int Root, L; int newnode() { for (int i = 0; i < cha; i++) next[L][i] = -1; end[L] = -1;//数据域 L++; return L - 1; } void init() { L = 0; Root = newnode(); } void insert(char s[], int id) { int len = strlen(s); int now = Root; int ti; for (int i = 0; i < len; i++) { ti = s[i];//ti下标 if (next[now][ti] == -1) next[now][ti] = newnode(); now = next[now][ti]; } end[now] = id;//数据域 } void build() { queue<int>Q; fail[Root] = Root; for (int i = 0; i < cha; i++) { if (next[Root][i] == -1) next[Root][i] = Root; else { fail[next[Root][i]] = Root; Q.push(next[Root][i]); } } while (!Q.empty()) { int now = Q.front(); Q.pop(); for (int i = 0; i < cha; i++) { if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]] = next[fail[now]][i]; Q.push(next[now][i]); } } } } bool query(char buf[], int n) { int len = strlen(buf); int now = Root; int ti; bool flag = false; for (int i = 0; i < len; i++) { ti = buf[i];//ti下标 now = next[now][ti]; int temp = now; while (temp != Root) { if (end[temp] != -1) //数据域 { flag = true; used[end[temp]] = TRUE;//数据域 } temp = fail[temp]; } } return flag; } void debug() { for (int i = 0; i < L; i++) { printf("id = %3d, fail = %3d, end = %3d, \n", i, fail[i], end[i]); // printf("word= ["); // for(int j=0;j<cha;j++) // printf("%2c", j+'a'); // printf("]\n"); printf("chi = ["); for (int j = 0; j < cha; j++) printf("%2d", next[i][j]); printf("]\n\n"); } }};char buf[10010];Trie ac;int main(){#ifdef DeBUGs freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);#endif int n, m; while (scanf("%d", &n) + 1) { ac.init(); for (int i = 1; i <= n; i++) { scanf("%s", buf); ac.insert(buf, i); } ac.build(); // ac.debug(); int ans = 0; scanf("%d", &m); for (int i = 1; i <= m; i++) { memset(used, 0, sizeof(used)); scanf("%s", buf); if (ac.query(buf, n)) { ans++; printf("web %d:", i); for (int j = 1; j <= n; j++) { if (used[j]) { printf(" %d", j); } } printf("\n"); } } printf("total: %d\n", ans); } return 0;}
非整合版,常规建树
关于
shr
h
下面的版建树是这样的
#define DeBUG#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <string>#include <set>#include <sstream>#include <map>#include <list>#include <bitset>using namespace std ;#define zero {0}#define INF 0x3f3f3f3f#define EPS 1e-6typedef long long LL;const double PI = acos(-1.0);//#pragma comment(linker, "/STACK:102400000,102400000")inline int sgn(double x){ return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}#define N 100005#define Root 0#define cha 129struct node{ int data; int count; int fail; int next[cha];};node tree[N];void init(node &a, int data){ a.data = data; a.count = 0; a.fail = Root; for (int i = 0; i < cha; i++) a.next[i] = -1;}int ID = 1;void Insert(char s[], int id){ int p = Root; for (int i = 0; s[i]; i++) { int data = s[i]; if (tree[p].next[data] == -1) { init(tree[ID], data); tree[p].next[data] = ID; ID++; } p = tree[p].next[data]; } tree[p].count = id;}void AC_automation(){ queue<node>Q; Q.push(tree[Root]); while (!Q.empty()) { node now = Q.front(); Q.pop(); for (int j = 0; j < cha; j++) { if (now.next[j] != -1) { if (now.data == -1) tree[now.next[j]].fail = Root; else { int t = now.fail; while (t != Root && tree[t].next[j] == -1) { t = tree[t].fail; } tree[now.next[j]].fail = max(tree[t].next[j], Root); } Q.push(tree[now.next[j]]); } } }}bool is[1005];int get_ans(char s[]){ int p = Root, ans = 0; for (int i = 0; s[i]; i++) { int t = s[i]; while (tree[p].next[t] == -1 && p) { p = tree[p].fail; } p = tree[p].next[t]; if (p == -1) { p = Root; continue; } int j = p; while (tree[j].count) { ans++; is[tree[j].count] = 1; j = tree[j].fail; } // 如果走到头以后当前字母不是关键字终点然而其fail指针指向字母是关键字终点的话,应当加入此关键值 if (tree[ tree[j].fail ].count) { ans++; is[tree[ tree[j].fail ].count] = 1; } } return ans;}char word[10005];char code[10005];int main(){#ifdef DeBUGs freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);#endif int n; while (scanf("%d", &n) + 1) { int m; init(tree[Root], -1); for (int i = 1; i <= n; i++) { scanf("%s", word); Insert(word, i); } AC_automation(); scanf("%d", &m); int total = 0; for (int j = 1; j <= m; j++) { memset(is, 0, sizeof(is)); scanf("%s", code); int num = get_ans(code); if (num != 0) { total++; printf("web %d:", j); for (int i = 1; i <= n; i++) { if (is[i]) { printf(" %d", i); } } printf("\n"); } } printf("total: %d\n", total); } return 0;}
0 0
- HDU2896AC自动机模板
- hdu2896ac自动机模板
- hdu2896ac自动机
- hdu2896AC自动机
- HDU2896ac自动机版+可以改字典树
- 【AC自动机】AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- 后缀自动机 模板
- AC自动机模板 hdu2222
- hdu4622 后缀自动机 模板
- AC自动机模板
- AC自动机模板
- 数据结构--AC自动机--模板
- R语言数据挖掘值关联规则挖掘
- js事件
- Python基础
- POJ 3187 Backward Digit Sums
- group by 深入总结
- HDU2896AC自动机模板
- javascript 实现压缩文件夹
- 线段树区间维护hdu3308
- Android编译后的目录结构
- PHP字符串处理
- HTML基础
- 网络原理制作bt采集蜘蛛
- Android 异步线程学习之 AsyncTask介绍
- 现在公开一个DHT网络爬虫