AC自动机 ( 动态建树模板 )——Keywords Search ( HDU 2222 )
2016-07-29 14:42
369 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2222
分析:
给出n个单词建树,然后给出一个字符串,搜索字符串里出现了多少个单词。直接套用AC自动机模板就可以。
AC自动机模板(含解析):
AC代码:
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; }
相关文章推荐
- HDU 2222 Keywords Search(我的第一道AC自动机,模板题)
- hdu 2222 keywords search (AC自动机 模板)
- HDU-2222 Keywords Search (AC自动机模板)
- hdu 2222(AC自动机模板)
- hdu 2222 AC自动机模板题
- HDU 2222 Keywords Search (初学AC自动机)
- hdu 2222 AC自动机模板题(指针版+数组版)
- hdu 2222 ac自动机模板
- HDU 2222 Keywords Search 【AC自动机模板】
- AC自动机 - 多模式串匹配问题的基本运用 + 模板题 --- HDU 2222
- HDU 2222 Keywords Search(AC自动机 模板)
- 【AC自动机详解+入门模板】HDU 2222
- Keywords Search - HDU 2222(AC自动机模板)
- AC自动机学习小记 Hdu 2222 Keywords Search (模板)
- hdu 2222 ac自动机模板题
- hdu 2222 Keywords Search(AC自动机模板)
- hdu 2222 Keywords_ac自动机模板
- hdu 2222 AC自动机模板题
- HDU 2222 AC自动机模板
- HDU 2222 Keywords Search (AC自动机模板)