AC自动机入门
Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一。学习AC自动机之前得先有Trie树和KMP模式匹配算法的基础。
AC自动机算法分为3步:1.构造一棵tire树 2.构造失败指针 3.进行模式匹配
AC自动机的优化:Trie图
1 5 she he say shr her yasherhs
3
题目大意:求给定单词在文章中出现的次数
题目分析:裸的多模式匹配,ac机模板题
#include <cstdio> #include <cstring> #include <queue> using namespace std; int const MAX = 1e6 + 5; struct node //Trie树 { int cnt; //单词的个数 node *next[26]; //叶子结点 node *fail; //失败指针 node() //初始化 { cnt = 0; memset(next, NULL, sizeof(next)); fail = NULL; } }; char word[51], text[MAX]; //Trie的构造 void Insert(node *p, char *s) { for(int i = 0; s[i] != '\0'; i++) { int idx = s[i] - 'a'; if(p -> next[idx] == NULL) p -> next[idx] = new node(); p = p -> next[idx]; } p -> cnt ++; //表示该单词出现过,并保存出现次数 } void AC_Automation(node *root) { queue <node*> q; //结点队列 q.push(root); //得到fail指针 while(!q.empty()) { node *p = q.front(); q.pop(); for(int i = 0; i < 26; i++) { if(p -> next[i]) //判断该结点是否存在 { //root下第一层结点的失败指针都指向root if(p == root) p -> next[i] -> fail = root; //当前结点的失败指针指向其失败结点的儿子结点 else p -> next[i] -> fail = p -> fail -> next[i]; q.push(p -> next[i]); } else //trie图优化 { if(p == root) p -> next[i] = root; else p -> next[i] = p -> fail -> next[i]; } } } } int Query(node *root) { int cnt = 0, len = strlen(text); node *p = root; for(int i = 0; i < len; i++) { int idx = text[i] - 'a'; while(!p -> next[idx] && p != root) p = p -> fail; p = p -> next[idx]; if(!p) p = root; node *tmp = p; while(tmp != root) { if(tmp -> cnt >= 0) { cnt += tmp -> cnt; tmp -> cnt = -1; } else break; tmp = tmp -> fail; } } return cnt; } int main() { int T; scanf("%d", &T); while(T--) { node *root = new node(); int n; scanf("%d", &n); while(n--) { scanf("%s", word); Insert(root, word); } AC_Automation(root); scanf("%s", text); printf("%d\n", Query(root)); } }
HDU 2222 Keywords Search (AC自动机入门 模板)
原文地址:http://blog.csdn.net/tc_to_top/article/details/44087385