典型的AC自动机题目,模板题但是初次学的AC自动机,错了n多次。
题目大意:给出n个字符串,然后再给出一个主串,求这个n个字符串中有几个字符串是是主串的子串?
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
#define N 1000005
char word[N];
int head,tail;
struct node
{
node *fail;
int cnt;
node *next[26];
node()
{
memset(next,0,sizeof(next));
fail=NULL;
cnt=0;
}
}*que[5000005];
node *root;
void Insert(char msg[])
{
int i=0;
node*ptr=root;
int k;
while(msg[i])
{
k=msg[i]-'a';
if(ptr->next[k]==NULL)
ptr->next[k]=new node();
ptr=ptr->next[k];
i++;
}
ptr->cnt++;
}
void build_ac()
{
que[tail++]=root;
while(tail!=head)
{
node *cur=que[head++];
node*ptr=NULL;
for(int i=0;i<26;i++)
{
if(cur->next[i]!=NULL)
{
if(cur==root)cur->next[i]->fail=root;
else
{
ptr=cur->fail;
while(ptr!=NULL)
{
if(ptr->next[i]!=NULL)
{
cur->next[i]->fail=ptr->next[i];
break;
}
ptr=ptr->fail;
}
if(ptr==NULL)
cur->next[i]->fail=root;
}
que[tail++]=cur->next[i];
}
}
}
}
int search_word(char msg[])
{
int i=0;
node*ptr=root;
int k;
int ans=0;
while(msg[i])
{
k=msg[i]-'a';
while(ptr->next[k]==NULL && ptr!=root)ptr=ptr->fail;
ptr=ptr->next[k];
if(ptr==NULL)ptr=root;
node *tmp=ptr;
while(tmp!=NULL && tmp->cnt!=-1)
{
ans+=tmp->cnt;
tmp->cnt=-1;
tmp=tmp->fail;
}
i++;
}
return ans;
}
void del(node*head)
{
for(int i=0;i<26;i++)
if(head->next[i]!=NULL)
del(head->next[i]);
delete head;
}
int main()
{
char msg[55];
int T,n;
scanf("%d",&T);
while(T--)
{
root=new node();
head=tail=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",msg);
Insert(msg);
}
build_ac();
scanf("%s",word);
printf("%d\n",search_word(word));
del(root);
}
return 0;
}