只在每个模式串最后记录模式串的顺序号,中间全设为0即可,然后AC自动机跑一遍。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <malloc.h>
using namespace std;
#define maxn 94
bool vis[550];
struct Trie
{
Trie *fail;
Trie *next[maxn];
int num;
Trie()
{
for(int i=0;i<maxn;i++)
next[i]=NULL;
fail=NULL;
num=0;
}
}*root;
void inserttrie(char *str,int k)
{
Trie *p=root;
for(int i=0;str[i]!='\0';i++)
{
int id=str[i]-' ';
if(p->next[id]==NULL)
{
p->next[id]=new Trie;
}
p=p->next[id];
}
p->num=k;
}
void buildfail()
{
Trie *son,*temp,*p=root;
queue<struct Trie*>que;
que.push(p);
while(!que.empty())
{
temp=que.front();
que.pop();
for(int i=0;i<maxn;i++)
{
son=temp->next[i];
if(son!=NULL)
{
if(temp==root)son->fail=root;
else
{
p=temp->fail;
while(p)
{
if(p->next[i])
{
son->fail=p->next[i];
break;
}
p=p->fail;
}
if(!p)
son->fail=root;
}
que.push(son);
}
}
}
}
int querry(char *str)
{
int ans=0;
Trie *p,*temp;
p=root;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int id=str[i]-' ';
while(p!=root&&p->next[id]==NULL)p=p->fail;
p=p->next[id];
if(!p)p=root;
temp=p;
while(temp!=root)
{
vis[temp->num]=1; /*设置vis,模式串全走完了,即在主串中,则令模式串顺序号为vis的下标,并改成1,方便统计*/
if(temp->num!=0)
{
ans++;
}
temp=temp->fail;
}
}
return ans;
}
int main()
{
int n,m,i;
char st[330],web[10100];
int total=0,flag;
root=new Trie;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",st);
inserttrie(st,i);
}
buildfail();
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%s",web);
memset(vis,0,sizeof(vis));
flag=querry(web);
if(flag!=0)
{
total++;
printf("web %d:",i);
for(int j=1;j<=n;j++)
{
if(vis[j])
printf(" %d",j);
}
printf("\n");
}
}
printf("total: %d\n",total);
return 0;
}