题意:首先输入n个单词,然后输入一个字符串,题目要求的事在传中可以找到几个开始输入的单词。
分析:这是我做的第一个AC自动机模板题,对于刚开始学习AC自动机的人我推荐两个资料:第一个:file:///C:/Users/Administrator/AppData/Local/Temp/360zip$Temp/360$0/AC自动机算法详解%20-%20极限定律%20-%20C++博客.mht
第二个资料:这个我觉得也挺好的,http://www.cnblogs.com/zhuangli/archive/2008/08/13/1267249.html
看完这两个资料之后这道题就不是问题了!
#include<iostream> #include<string.h> #include<stdio.h> using namespace std; struct node{ int count; struct node *fail; struct node *next[26]; node() { fail=NULL; memset(next,NULL,sizeof(next)); count=0; } }*queue[500005]; struct node *root; char keyword[55],str[1000005]; void build(char *str)//建立字典树 { struct node *p=p=root; int index; for(;*str!='\0';str++) { index=*str-'a'; if(p->next[index]==NULL) p->next[index]=new node; p=p->next[index]; } p->count++; } void AC_tree()//构造失败指针 { int f,r,i; struct node *p,*temp; root->fail=NULL; f=0;r=0; queue[r++]=root; while(f!=r) { p=queue[f++]; for(i=0;i<26;i++) { if(p->next[i]!=NULL) { temp=p->fail; while(temp!=NULL) { if(temp->next[i]!=NULL) { p->next[i]->fail=temp->next[i]; break; } temp=temp->fail; } if(temp==NULL) p->next[i]->fail=root; queue[r++]=p->next[i]; } } } } int find(char *str)//单词查找 { int index; int sum=0; struct node *p,*temp; p=root; for(;*str!='\0';str++) { index=*str-'a'; while(p->next[index]==NULL&&p!=root) p=p->fail; p=p->next[index]; if(p==NULL) p=root; temp=p; while(temp!=root&&temp->count!=-1) { sum=sum+temp->count; temp->count=-1; temp=temp->fail; } } return sum; } void del(struct node *root) { int i; for(i=0;i<26;i++) { if(root->next[i]!=NULL) del(root->next[i]); } delete(root); } int main() { int T,n; while(scanf("%d",&T)!=EOF) { while(T--) { root=new node; scanf("%d",&n); getchar(); while(n--) { scanf("%s",keyword); build(keyword); } AC_tree(); scanf("%s",str); printf("%d\n",find(str)); del(root); } } return 0; }
用静态数组模拟:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
struct node{
int next[26];
int fail;
int count;
void init()
{
memset(next,0,sizeof(next));
fail=0;
count=0;
}
};
struct node a[500005];
int n,tot;
char keyword[55];
char S[1000005];
void chushihua()
{
tot=0;
a[0].init();
}
void insert(char *str)
{
int index,p;
p=0;
for(;*str!='\0';str++)
{
index=*str-'a';
if(a[p].next[index]==0)
{
a[++tot].init();
a[p].next[index]=tot;
}
p=a[p].next[index];
}
a[p].count++;
}
void build_fail()
{
int i,p,son,cur;
queue<int>Q;
Q.push(0);
while(!Q.empty())
{
p=Q.front();
Q.pop();
for(i=0;i<26;i++)
{
if(a[p].next[i]!=0)
{
son=a[p].next[i];
cur=a[p].fail;
if(p==0)
a[son].fail=0;
else
{
while(cur!=0&&a[cur].next[i]==0)
cur=a[cur].fail;
a[son].fail=a[cur].next[i];
}
Q.push(son);
}
}
}
}
int solve()
{
int i,index,p=0,temp,res;
res=0;
for(i=0;S[i]!='\0';i++)
{
index=S[i]-'a';
while(p!=0&&a[p].next[index]==0)
p=a[p].fail;
if(a[p].next[index]!=0)
p=a[p].next[index];
temp=p;
while(temp&&a[temp].count!=-1)
{
res=res+a[temp].count;
a[temp].count=-1;
temp=a[temp].fail;
}
}
return res;
}
int main()
{
int T;
while(scanf("%d",&T)!=EOF)
{
while(T--)
{
chushihua();
scanf("%d",&n);
getchar();
while(n--)
{
scanf("%s",keyword);
insert(keyword);
}
build_fail();
scanf("%s",S);
printf("%d\n",solve());
}
}
return 0;
}