HDOJ-2222 Keywords Search 字典树+AC自动机(三叉树实现字典树)
来源:互联网 发布:js小图传给大图 编辑:程序博客网 时间:2024/04/29 03:50
啊啊,我还以为不可能成功的,放下了两天,今天无聊再敲一下。
原来我一直都读错题了呀。
只是计算出现的模式串的数目,重复的也只算一次。
把之前写的深度优先遍历子树都改成了广度优先遍历。
6000+k的内存,对比别人都是至少12000的内存,还是可以不错的。
代码量有点多和时间复杂度比trie树上的ac自动机大,并且一般acm里的都是二十六个字母,并不会卡那么点内存。
不管怎么说,证实三叉树可以构造AC自动机了。
/* 这个主要把递归深度优先遍历改成了非递归的广度优先的遍历 */#include <cstdio>#include <cstring>#include <queue>#include <iostream>using namespace std;typedef int Nodelink;const int maxn = 8000101;//内存池大小Nodelink Node[maxn][3]; //三叉树的节点.int cnt[maxn]; //以该节点为结束的字符串的数目。char elem[maxn]; //节点保存的字符。int top; //模拟内存池地址char str[60];char pattern[1000010];Nodelink fail[maxn];int tque[maxn], tail, head;//不用STL的queueinline Nodelink newNode(char ch) //创建一个节点{ top ++; Node[top][0] = Node[top][1] = Node[top][2] = 0; cnt[top] = 0; elem[top] = ch; return top;}void Insert() //插入模式串{ int len = strlen(str); Nodelink p = 1; for(int i = 0; i < len; i++) { if(!Node[p][2]) Node[p][2] = newNode(str[i]); p = Node[p][2]; while(elem[p] != str[i]) { //二叉树插入元素,保证有序 if(str[i] < elem[p]) { if(!Node[p][0]) Node[p][0] = newNode(str[i]); p = Node[p][0]; } else { if(!Node[p][1]) Node[p][1] = newNode(str[i]); p = Node[p][1]; } } } cnt[p] ++; //以编号为p的结点为结尾的模式串的数目。}int que[28];int findFail(Nodelink fp, Nodelink p){ while(elem[fp] != elem[p]) { if(elem[p] < elem[fp]) if(!Node[fp][0]) break; else fp = Node[fp][0]; else if(!Node[fp][1]) break; else fp = Node[fp][1]; } if(elem[fp] == elem[p]) { fail[p] = fp; return 1; } return 0;}void travelPre(Nodelink p, Nodelink pre){ int tp = 0, front = 0; que[++tp] = p; Nodelink tmp = 0; while(front < tp) { p = que[++front]; tmp = fail[pre]; while(tmp && !findFail(Node[tmp][2], p)) tmp = fail[tmp]; if(tmp == 0) fail[p] = 1; tque[++head] = p; if(Node[p][0]) que[++tp] = Node[p][0]; if(Node[p][1]) que[++tp] = Node[p][1]; }}void getFail() //生成fail指针{ head = tail = 0; tque[++head] = 1; fail[1] = 0; while(tail != head) { Nodelink pre = tque[++tail]; if(Node[pre][2]) travelPre(Node[pre][2], pre); }}int ans = 0;int matchCH(char ch, Nodelink p, Nodelink &pre){ int tp = 0; int front = 0; que[++tp] = p; while(front < tp) { p = que[++front]; if(elem[p] == ch) { pre = p; int fp = p; while(fp && cnt[fp] != -1) { ans += cnt[fp]; cnt[fp] = -1; fp = fail[fp]; } return 1; } if(Node[p][0])que[++tp] = Node[p][0]; if(Node[p][1])que[++tp] = Node[p][1]; } return 0;}void match(){ int idx = 0; Nodelink p = 1; while(pattern[idx]) { while(p && !matchCH(pattern[idx] , Node[p][2], p)) p = fail[p]; if(p == 0) p = 1; idx ++; }}int main(){ int t, n; scanf("%d", &t); while(t--) { top = 0; ans = 0; newNode('\0'); scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%s",str); Insert(); } scanf("%s", pattern); getFail(); match(); printf("%d\n", ans); } return 0;}
0 0
- HDOJ-2222 Keywords Search 字典树+AC自动机(三叉树实现字典树)
- (字典树+AC自动机) hdu 2222 Keywords Search
- HDU 2222 Keywords Search【AC自动机|字典树】
- hdoj 2222 Keywords Search 【字典树挤进1ms----啊--我要学AC自动机】
- hdoj-2222Keywords Search(AC自动机)
- 字典树+AC自动机
- 字典树 AC自动机
- hdu 2222 Keywords Search(字典树)
- 【AC自动机】 HDOJ 2222 Keywords Search
- hdoj--2222 Keywords Search(AC自动机)
- HDOJ 题目2222 Keywords Search(AC自动机)
- 字典树+KMP+AC自动机
- (三叉字典树)二叉树套字典树
- hdU 2222 Keywords Search(AC自动机)
- hdu 2222 Keywords Search(AC自动机)
- hdu 2222 Keywords Search(AC自动机)
- HDU 2222 Keywords Search (AC自动机)
- hdu - 2222 - Keywords Search(AC自动机)
- 《剑指offer》面试题4 替换空格
- 简单版猜拳游戏
- 正则表达式常用知识点总结
- 有思想的程序员
- Java的JDBC事务详解
- HDOJ-2222 Keywords Search 字典树+AC自动机(三叉树实现字典树)
- LayerMask的使用
- 批处理实例
- hdu1175
- 游戏Entity设计不完全整理(转)
- 北京师范大学第十二届程序设计竞赛
- Jump Game
- 很激动可以在CSDN写博
- Struts2实现文件上传报错(三)