基础AC自动机
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define MAXS 10005
#define MAXX 94
int ans[5];
struct acauto
{
queue<int> q;
int ch[MAXN][MAXX],fail[MAXN],last[MAXN];
int val[MAXN];
int sz;
void ini(){sz=1;memset(ch[0],0,sizeof(ch[0]));}
int idx(char c) {return c-'!';}
void insert(char *s,int v)
{
int pre=0,len=strlen(s);
for(int i=0;i<len;i++)
{
int next=idx(s[i]);
if(!ch[pre][next])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[pre][next]=sz++;
}
pre=ch[pre][next];
}
val[pre]=v;
}
int cnt;
void print(int j)
{
if(j)
{
ans[cnt]=val[j];
cnt++;
if(cnt==3) return ;
print(last[j]);
}
}
void find(char *s)
{
cnt=0;
int len=strlen(s),j=0;
for(int i=0;i<len;i++)
{
int next=idx(s[i]);
while(j&&!ch[j][next]) j=fail[j];
j=ch[j][next];
if(val[j]) print(j);
else if(last[j]) print(last[j]);
}
}
void getfail()
{
while(!q.empty()) q.pop();
fail[0]=0;
for(int next=0;next<MAXX;next++)
{
int u=ch[0][next];
if(u) {fail[u]=0;q.push(u);last[u]=0;}
}
while(!q.empty())
{
int pre=q.front();
q.pop();
for(int next=0;next<MAXX;next++)
{
int u=ch[pre][next];
if(!u) continue;
q.push(u);
int v=fail[pre];
while(v&&!ch[v][next]) v=fail[v];
fail[u]=ch[v][next];
last[u]=val[fail[u]]?fail[u]:last[fail[u]];
}
}
}
};
int n,m;
char s[MAXS],t[205];
acauto ac;
int main()
{
while(scanf("%d",&n)!=EOF)
{
ac.ini();
for(int i=1;i<=n;i++)
{
scanf("%s",t);
ac.insert(t,i);
}
ac.getfail();
int cnt=0;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",s);
ac.find(s);
if(ac.cnt)
{
printf("web %d:",i);
sort(ans,ans+ac.cnt);
for(int j=0;j<ac.cnt;j++) printf(" %d",ans[j]);
printf("\n");
cnt++;
}
}
printf("total: %d\n",cnt);
}
return 0;
}