https://vjudge.net/problem/HDU-3065
思路:和普通的自动机区别不大。输入模式串的时候要注意带空格的输入。对于模式串中不在大写字母范围内的可以让他变为‘Z’+1,这样就可以节省空间。在进行查询操作的时候,遇到非大写字母不能if(.....) continue,因为这样就相当于把非大写字母从模式串中去掉了。对于AAA这种情况,可在字典树中加一个cnt计数。第2个A的fail是指向第一个A的,详情见代码83-88行。
#include<bits/stdc++.h>
#define maxn 1005
#define N 20000005
using namespace std;
char s[maxn][55];
int ans[maxn];
char pattern[N];
struct node{
node *next[27];
node *fail;
int index;
int cnt;
node()
{
memset(next,NULL,sizeof(next));
fail=NULL;
index=0;
cnt=0;
}
};
node *root;
void Insert(char str[],int index)
{
node *p=root;
for(int i=0;str[i]!='\0';i++)
{
int id=str[i]-'A';
if(p->next[id]==NULL)
p->next[id]=new node;
p=p->next[id];
}
p->index=index;
}
void build_fail_pointer()
{
queue<node *>Q;
Q.push(root);
node *temp,*p;
while(!Q.empty())
{
temp=Q.front();Q.pop();
for(int i=0;i<27;i++)
{
if(temp->next[i]!=NULL)
{
if(temp==root)
temp->next[i]->fail=root;
else
{
p=temp->fail;
while(p)
{
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.push(temp->next[i]);
}
}
}
}
void ac_automation(char pattern[])
{
node *p=root;
for(int i=0;pattern[i]!='\0';i++)
{
if(pattern[i]<'A'||pattern[i]>'Z')
pattern[i]='Z'+1;
int id=pattern[i]-'A';
while(p->next[id]==NULL&&p!=root) p=p->fail;
p=p->next[id];
if(p==NULL) p=root;
node *temp=p;
while(temp!=root)
{
if(temp->index!=0)
{
temp->cnt++;
ans[temp->index]=temp->cnt;
}
temp=temp->fail;
}
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF){
memset(ans,0,sizeof(ans));
root=new node;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]);
Insert(s[i],i);
}
getchar();
gets(pattern);
build_fail_pointer();
ac_automation(pattern);
for(int i=1;i<=n;i++)
{
if(ans[i]!=0)
{
printf("%s: %d\n",s[i],ans[i]);
}
}
}
return 0;
}