AC自动机是由KMP算法和字典数算法相结合的一个多模匹配的算法
该算法分为两点:
(1)构造pattern的字典数,求fail指针;
(2)进行模式匹配,与kmp有点类似。
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1251
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<malloc.h>
using namespace std;
const int nmax=1001000;
char text[nmax];
char word[55];
struct node
{
int cnt;
int v;
struct node *fail;//失败指针
struct node *next[26];
node (){
v=0;cnt=0;memset(next,NULL,sizeof(next));fail=NULL;
}
}*Q[500001];//构造字典树的树据结构,Q为队列,求fail指针要用。
int head,tail;
void creat(char *str,node *root)
{
int len=strlen(str);
node *p=root,*q;
for(int i=0;i<len;i++)
{
int id=str[i]-'a';
if(p->next[id]==NULL)
{
q=(node *)new node();
// q->cnt=1;
p->next[id]=q;
p=p->next[id];
}
else
{
p=p->next[id];
// p->cnt++;
}
}
p->cnt++;
}//生成字典树
void AC_Auto(node * root)
{
int i;
root->fail=NULL;
Q[head++]=root;
while(head!=tail)
{
node *temp=Q[tail++];
node *p=NULL;
for(i=0;i<26;i++)
if(temp->next[i]!=NULL)
{
if(temp==root) temp->next[i]->fail=root;
else {
p=temp->fail;
while(p!=NULL)
{
if(p->next[i]!=NULL)
{
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL) temp->next[i]->fail=root;
}
Q[head++]=temp->next[i];
}
}
}//求fail指针
int query(node *root)
{
int i=0,index,Cnt=0,len=strlen(text);
node *p=root;
while(text[i])
{
index=text[i]-'a';
while(p->next[index]==NULL&&p!=root) p=p->fail;
p=p->next[index];
p=(p==NULL)?root:p;
node *temp=p;
while(temp!=root&&temp->cnt!=-1)
{
Cnt+=temp->cnt;
temp->cnt=-1;
temp=temp->fail;
}
i++;
}
return Cnt;
}//匹配,返回存在单词个数
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
node *root=new node();
int N;
head=tail=0;
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%s",word);
creat(word,root);
}
AC_Auto(root);
scanf("%s",text);
printf("%d\n",query(root));
}
return 0;
}