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