Keywords Search - HDU 2222(AC自动机模板)
2015-08-22 16:43
435 查看
题目大意:输入几个子串,然后输入一个母串,问在母串里面包含几个子串。
分析:刚学习的AC自动机,据说这是个最基础的模板题,所以也是用了最基本的写法来完成的,当然也借鉴了别人的代码思想,确实是个很神奇的东西,如果不懂KMP的话,最好先学学KMP再来学这个,会理解的更深刻一些。
代码如下:
=======================================================================================================================
分析:刚学习的AC自动机,据说这是个最基础的模板题,所以也是用了最基本的写法来完成的,当然也借鉴了别人的代码思想,确实是个很神奇的东西,如果不懂KMP的话,最好先学学KMP再来学这个,会理解的更深刻一些。
代码如下:
=======================================================================================================================
#include<stdio.h> #include<string.h> #include<algorithm> #include<queue> using namespace std; const int MAXN = 1e6+7; const int MAXM = 26; const int oo = 1e9+37; char MumStr[MAXN];///母串 struct Ac_Trie_Node {///Fail 失败节点 Ac_Trie_Node *Fail, *next[MAXM]; int leaf;///已这个节点为叶子节点的数目 }; void Insert(Ac_Trie_Node *root, char s[]) {///插入所有的模式串 Ac_Trie_Node *p = root; for(int i=0; s[i]; i++) { int k = s[i]-'a'; if(p->next[k] == NULL) p->next[k] = new Ac_Trie_Node(); p = p->next[k]; } p->leaf += 1; } void GetFail(Ac_Trie_Node *root) {///构造失败指针 queue<Ac_Trie_Node *> Q; Ac_Trie_Node *p = root, *temp; for(int i=0; i<MAXM; i++) { if(p->next[i] != NULL) { p->next[i]->Fail = root; Q.push(p->next[i]); } } while(Q.size()) { p = Q.front();Q.pop(); for(int i=0; i<MAXM; i++) if(p->next[i]) {///如果节点p的next[i]不为空 temp = p->Fail;///查找另一个最近的next[i]不为空的地方 while(temp != NULL) { if(temp->next[i] != NULL) {///查找到 p->next[i]->Fail = temp->next[i]; break; } temp = temp->Fail; } if(temp == NULL) p->next[i]->Fail = root; Q.push(p->next[i]); } } } void FreeTrie(Ac_Trie_Node *root) {///释放内存 Ac_Trie_Node *p = root; for(int i=0; i<MAXM; i++) { if(p->next[i] != NULL) FreeTrie(p->next[i]); } free(p); } int Query(Ac_Trie_Node *root) { Ac_Trie_Node *p = root, *temp; int sum=0; for(int i=0; MumStr[i]; i++) { int k = MumStr[i]-'a'; while(!p->next[k] && p != root) p = p->Fail; if(!p->next[k])continue;///根节点下面没有这个字母 temp = p = p->next[k]; while(temp != root && temp->leaf != -1) {///查找路径上的所有子节串,因为每个子串只出现一次,所以赋值为-1,防止重搜 sum += temp->leaf; temp->leaf = -1; temp = temp->Fail; } } return sum; } int main() { int T; scanf("%d", &T); while(T--) { int M; char s[107]; Ac_Trie_Node *root = new Ac_Trie_Node(); scanf("%d", &M); while(M--) { scanf("%s", s); Insert(root, s); } GetFail(root); scanf("%s", MumStr); int ans = Query(root); printf("%d\n", ans); FreeTrie(root); } return 0; }
相关文章推荐
- 主流HTML5游戏框架的分析和对比
- LeetCode2.1.12(Next Permutation)
- PHP 面向对象之__toString
- C#通过调用系统命令执行R脚本
- 如何检索Android设备的唯一ID
- Python之requests的安装
- 有关label的学习笔记
- Problem 2089 数字游戏
- Android中静态变量(static)的使用
- 关于RadioGroup某个item设置为check后,会一直选中的问题
- Java中static关键字
- 多校The shortest problem
- Python第一天 - 函数
- hdu 1251 统计难题(字典树)
- LeetCode2.1.11(Remove Element)
- 淘宝天猫店铺装修问题与技巧性经验汇总
- UIButton及UITextfield
- Java Map接口总览
- 一个有趣的算法题。。。
- hdu 2222 Keywords Search(ac自动机)