【题意】就是给你一些单词,和一个字符串。问你有这个字符串中有几个单词;
【题解】AC自动机裸体;我讲的不详细,还望见谅,具体看代码。
(程序中我最大的不爽是,不会删除节点,我这里的不知道有没有效,我先交了没有delete的,再交了加了的。但交上去内存前后相差不多。希望可以被指出)。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define null 0
struct point
{
point *next[26],*fail;
int cont;
point(){
fail=null;
memset(next,null,sizeof(next));
cont=0;
}
}*g[510001];
point *root=new point();
char a[1000001];
char b[51];
inline void insert()
{
point *p=root;
int i=1,tail=strlen(b+1),k;
while(i<=tail)
{
k=(int)b[i]-97;
if((p->next[k])==null)
p->next[k]=new point();
p=p->next[k];
i++;
}
p->cont++;
}
inline void setfail()
{
int head=0,tail=1;
g[tail]=root;
while(head<tail)
{
point *p=g[++head];
for(int i=0;i<=25;i++)
if(p->next[i]!=null){
if(p==root)p->next[i]->fail=root;
else{
point *t=p->fail;
while((t!=root)&&(t->next[i]==null))t=t->fail;
if(t->next[i]!=null)p->next[i]->fail=t->next[i];
else p->next[i]->fail=root;
}
g[++tail]=p->next[i];
}
}
}
inline int matching()
{
int ans=0,i=1,t=strlen(a+1),k;point *p=root;
while(i<=t)
{
k=(int)a[i]-97;
while((p->next[k]==null) && (p!=root))p=p->fail;
if(p->next[k]==null)p=root;
else p=p->next[k];
point *tmp=p;
while((tmp!=root) && ((tmp->cont)!=-1))
{
ans+=tmp->cont;
tmp->cont=-1;
tmp=tmp->fail;
}
i++;
}
return ans;
}
inline void delet()
{
int head=0,tail=1;
g[tail]=root;
while(head<tail)
{
point p=*g[++head];
delete(g[head]);
for(int i=0;i<=25;i++)
if(p.next[i]!=null)
g[++tail]=p.next[i];
}
}
int main()
{
int t,n;
scanf("%d",&t);
for(;t;t--){
root=new point();
root->fail=root;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",b+1);
insert();
}
setfail();
scanf("%s",a+1);
printf("%d\n",matching());
delet();
}
return 0;
}