HDU 3065 (AC自动机)
来源:互联网 发布:mysql数据库篡改 黑客 编辑:程序博客网 时间:2024/05/29 13:25
病毒侵袭持续中
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9999 Accepted Submission(s): 3500
Problem Description
小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?
Input
第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
Output
按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
Sample Input
3AABBCCooxxCC%dAAAoen....END
Sample Output
AA: 2CC: 1HintHit:题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。计数策略也可一定程度上从Sample中推测。
Source
2009 Multi-University Training Contest 16 - Host by NIT
Recommend
lcy
题解:AC自动机模板题,不过要改一下模板,这里是所有可见字符,那么我们只能把数组开到叶子节点个数开到130。最大节点个数是n*len,所以开1000*50就可以了
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<string> #include<bitset> #include<utility> #include<functional> #include<iomanip> #include<sstream> #include<ctime> using namespace std; #define N int(1e5) #define inf int(0x3f3f3f3f) #define mod int(1e9+7) typedef long long LL; const int SIGMA_SIZE = 130; const int MAXNODE = 101000; const int MAXS = 1005; map<string,int> ms; //ms是为了满足特殊要求,比如模板串相同时 struct ACautomata { int ch[MAXNODE][SIGMA_SIZE]; int f[MAXNODE]; // fail函数 int val[MAXNODE]; // 每个字符串的结尾结点都有一个非0的val int last[MAXNODE]; // 输出链表的下一个结点 int cnt[MAXS]; int sz; void init() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); memset(cnt, 0, sizeof(cnt)); ms.clear(); } // 字符c的编号 int idx(char c) { return int(c); } // 插入字符串。v必须非0 void insert(char *s, int v) { int u = 0, 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] = v; ms[string(s)] = v; } // 递归打印匹配文本串str[i]结尾的后缀,以结点j结尾的所有字符串 void print(int i,int j) { if(j) { cnt[val[j]]++; print(i,last[j]); } } // 在T中找模板 void find(char* T) { int n = strlen(T); int j = 0; // 当前结点编号,初始为根结点 for(int i = 0; i < n; i++) { // 文本串当前指针 int c = idx(T[i]); j = ch[j][c]; if(val[j]) print(i,j); else if(last[j]) print(i,last[j]); // 找到了! } } // 计算fail函数 void getFail() { queue<int> q; f[0] = 0; // 初始化队列 for(int c = 0; c < SIGMA_SIZE; c++) { int u = ch[0][c]; if(u) { f[u] = 0; q.push(u); last[u] = 0; } } // 按BFS顺序计算fail while(!q.empty()) { int r = q.front(); q.pop(); for(int c = 0; c < SIGMA_SIZE; c++) { int u = ch[r][c]; if(!u) { ch[r][c]=ch[f[r]][c]; continue; } q.push(u); int v = f[r]; while(v && !ch[v][c]) v = f[v]; f[u] = ch[v][c]; last[u] = val[f[u]] ? f[u] : last[f[u]]; } } } }AC; #ifdef CDZSC #define debug(...) fprintf(stderr, __VA_ARGS__) #else #define debug(...) #endif char s[1005][100];char tmp[2000000+10];int main() { #ifdef CDZSC freopen("o.txt", "r", stdin); //freopen("o.txt","w",stdout); int _time_jc = clock(); #endif int n;while(~scanf("%d",&n)){AC.init();for(int i=1;i<=n;i++){scanf("%s",s[i]);AC.insert(s[i],i);}AC.getFail();scanf("%s",tmp);AC.find(tmp);for(int i=1;i<=n;i++){if(AC.cnt[i]>0){printf("%s: %d\n",s[i],AC.cnt[i]);}}}#ifdef CDZSC debug("time: %d\n", int(clock() - _time_jc)); #endif return 0; }
0 0
- hdu 3065(ac自动机)
- HDU 3065 (AC自动机)
- AC自动机(hdu 2896 hdu 3065)
- hdu 3065(AC自动机)
- HDU 3065 AC自动机
- hdu 3065 AC自动机
- HDU 3065(ac自动机)
- HDU 3065 AC自动机
- HDU 3065 AC自动机
- hdu 3065 AC自动机
- hdu 3065 AC自动机
- HDU 3065 (AC自动机)
- HDU 3065 AC自动机
- hdu 3065-AC自动机
- hdu 3065 ac自动机
- hdu 3065 AC自动机(指针+数组)
- HDU 3065 (AC自动机水题)
- AC自动机小结 (HDU 2222,HDU 2896,HDU 3065)
- 图的邻接矩阵
- 大志非才不就,大才非学不成—博文资源汇总
- 三和先生遺稿 1967年
- 如何用TextView显示Html格式的数据
- Linux进程间通信的几种方式总结--linux内核剖析(七)
- HDU 3065 (AC自动机)
- BZOJ1002 无向联通图的生成树计数
- Linux上监控网络带宽的18个常用命令
- NSOperationQueue GCD NSThread总结
- 自己动手写一个简单的MVC框架(第一版)
- BZOJ-1878 HH的项链 树状数组+莫队(离线处理)
- Android中接收系统广播消息
- 剑指offer:17 合并两个排序的链表
- 换无线网卡