AC自动机 ( 动态建树模板 )——Keywords Search ( HDU 2222 )
来源:互联网 发布:ipad软件下载排行榜 编辑:程序博客网 时间:2024/05/21 12:09
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2222分析:
给出n个单词建树,然后给出一个字符串,搜索字符串里出现了多少个单词。直接套用AC自动机模板就可以。AC自动机模板(含解析):
const int k = 26;const int MAXN = 500100;struct Node{ Node* ch[k], *fail; int match; void clear() { memset(this, 0, sizeof(Node)); }};Node * que[MAXN];struct ACAutomaton{ Node nodes[MAXN], *root, *superRoot, *cur; //全局变量 Node * newNode() //从内存池中初始化一个结点 { cur -> clear(); return cur++; } void clear() //清空整个字典树 { cur = nodes; superRoot = newNode(); root = newNode(); root -> fail = superRoot; for(int i=0;i<k;i++) //superRoot为虚拟的超级根结点,所有孩子均指向实际的根结点,减少建立自动机的代码量 superRoot -> ch[i] = root; superRoot->match = -1; } void insert(char *s)//插入每一个字符,match++ { Node * t = root; for(;*s;s++) { int x = *s - 'a'; if(t -> ch[x] == NULL) t -> ch[x] = newNode(); t = t -> ch[x]; } t -> match++; } void build() //使用自动机前,要先生成失配指针 { int p=0, q =0; que[q++] = root; while(p!=q) //BFS求失配指针【非常关键的一步,可以好好理解】 { Node*t = que[p++]; for(int i=0;i<k;i++) { if(t->ch[i]) { t -> ch[i] -> fail = t->fail ->ch[i]; que[q++] = t->ch[i]; }else t->ch[i] = t -> fail ->ch[i]; } } } int run(char *s) //计算s中模式串出现的次数 { int ans = 0; Node * t = root; for(; *s ; s++) { int x = *s - 'a'; t = t->ch[x]; //记住 t 每次迭代的值!!!便于理解 for(Node*u = t; u->match != -1;u = u->fail) { ans += u ->match; u -> match = -1; //避免重复计算 } } return ans; }};
- AC代码:
#include <cstdio>#include <iostream>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <cctype>#include <map>#include <set>#include <queue>using namespace std;typedef pair<int,int> Pii;typedef long long LL;typedef unsigned long long ULL;typedef double DBL;typedef long double LDBL;#define MST(a,b) memset(a,b,sizeof(a))#define CLR(a) MST(a,0)#define Sqr(a) ((a)*(a))const int k = 26;const int MAXN = 500100;struct Node{ Node* ch[k], *fail; int match; void clear() { memset(this, 0, sizeof(Node)); }};Node * que[MAXN];struct ACAutomaton{ Node nodes[MAXN], *root, *superRoot, *cur; //全局变量 Node * newNode() //从内存池中初始化一个结点 { cur -> clear(); return cur++; } void clear() //清空整个字典树 { cur = nodes; superRoot = newNode(); root = newNode(); root -> fail = superRoot; for(int i=0;i<k;i++) //superRoot为虚拟的超级根结点,所有孩子均指向实际的根结点,减少建立自动机的代码量 superRoot -> ch[i] = root; superRoot->match = -1; } void insert(char *s) { Node * t = root; for(;*s;s++) { int x = *s - 'a'; if(t -> ch[x] == NULL) t -> ch[x] = newNode(); t = t -> ch[x]; } t -> match++; } void build() //使用自动机前,要先生成失配指针 { int p=0, q =0; que[q++] = root; while(p!=q) //BFS求失配指针 { Node*t = que[p++]; for(int i=0;i<k;i++) { if(t->ch[i]) { t -> ch[i] -> fail = t->fail ->ch[i]; que[q++] = t->ch[i]; }else t->ch[i] = t -> fail ->ch[i]; } } } int run(char *s) //在自动机上与匹配串s进行匹配 { int ans = 0; Node * t = root; for(; *s ; s++) { int x = *s - 'a'; t = t->ch[x]; for(Node*u = t; u->match != -1;u = u->fail) { ans += u ->match; u -> match = -1; } } return ans; }};int n;ACAutomaton j;char s[1000100];int main(){ int T; scanf("%d", &T); while(T--) { scanf("%d", &n); j.clear(); while(n--) { scanf("%s", s); j.insert(s); } j.build(); scanf("%s", s); printf("%d\n", j.run(s)); } return 0;}
0 0
- AC自动机 ( 动态建树模板 )——Keywords Search ( HDU 2222 )
- 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自动机模板
- 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自动机模板)
- 【模板练习——AC自动机】Keywords Search HDU
- 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自动机模板题)
- hdu 2222 Keywords Search(AC自动机模板题)
- c++ new和不new对象的区别
- xss其他标签下的js用法总结大全 20160711
- 机器学习面试问题7
- POJ-3630 Phone List(字典树)
- android用aapt命令实现打包时替换资源
- AC自动机 ( 动态建树模板 )——Keywords Search ( HDU 2222 )
- Android傻瓜式分包插件
- PP详解-工单完成
- 常用的linux文件权限
- Presto Benchmark Driver 的使用
- 大量TIME_WAIT的终极详解和解决方案
- JS组件系列——表格组件神器:bootstrap table(二:父子表和行列调序)
- 黑马程序员:从零基础到精通的前端学习路线
- 五分钟战胜Python字符编码