#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<set>
using namespace std;
const int maxn=512;
int n,m,ans,res,que[maxn];
struct node
{
int idx,flag;
node *fail;
node *next[100];
node()
{
memset(next,0,sizeof(next));
idx=0;
flag=0;
fail=NULL;
}
};
void Insert(node *rt,char s[],int idx)
{
node *p=rt;
int i=0;
while(s[i])
{
int k=s[i++]-32;
if(p->next[k]==NULL)p->next[k]=new node();
p=p->next[k];
}
p->flag=1;//字符串结尾
p->idx=idx;//代表第几个字符串
}
void build_AC(node *rt)
{
int i,j=0;
queue<node*>q;
rt->fail=NULL;
q.push(rt);
while(!q.empty())
{
node *p=q.front();
q.pop();
for(i=0;i<100;i++)
{
if(p->next[i]!=NULL)//寻找当前子树的失败指针
{
if(p==rt)
{
p->next[i]->fail=rt;
}else
{
node *tmp=p->fail;
while(tmp!=NULL)
{
if(tmp->next[i]!=NULL)//找到失败指针
{
p->next[i]->fail=tmp->next[i];
// if(tmp->next[i]->flag==1) p->next[i]->flag=1;
break;
}
tmp=tmp->fail;
}
if(tmp==NULL)p->next[i]->fail=rt;//无法获取,当前子树的失败指针为根
}
q.push(p->next[i]);
}
}
}
}
void query_AC(node *rt,char s[])
{
int i=0,j;
node *p=rt;
while(s[i])
{
int k=s[i++]-32;
while(p->next[k]==NULL&&p!=rt)p=p->fail;//失配
p=p->next[k];
if(p==NULL)p=rt;//失配指针为根
node *tmp=p;
while(tmp!=rt)//&&!vis[tmp->idx]
{
if(tmp->idx)
que[ans++]=tmp->idx;
tmp=tmp->fail;
}
}
}
int main()
{
char s[12020];
char ss[210];
while(scanf("%d",&n)!=EOF)
{
int i,j;
ans=res=0;
node *rt=new node();
for(i=1;i<=n;i++)
{
scanf("%s",ss);
Insert(rt,ss,i);
}
build_AC(rt);
scanf("%d",&m);
for(ans=0,i=1;i<=m;i++)
{
scanf("%s",s);
query_AC(rt,s);
if(ans)
{
res++;
printf("web %d:",i);
sort(que,que+ans);
int cnt=unique(que,que+ans)-que;
for(j=0;j<cnt;j++)
cout<<" "<<que[j];
cout<<endl;
}
ans=0;
}
printf("total: %d\n",res);
}
return 0;
}
史上最裸 AC 自动机 第二弹
最新推荐文章于 2024-02-02 13:43:51 发布