测试地址:病毒侵袭
做法:就是AC自动机的模板题,网上教程很多,这里不再赘述。但是我写完之后交上去发现格式错误,结果在文末多输出个空行就对了...好迷啊...
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
char s[1000010];
int n,m,tot,root,now,total=0;
bool vis[510];
struct
{
int next[100010][128],fail[100010],end[100010];
int newnode()
{
end[++tot]=0;fail[tot]=0;
for(int i=0;i<128;i++)
next[tot][i]=0;
return tot;
}
void destroy()
{
tot=0;
root=newnode();
}
void insert()
{
int v=root,i=0;
while(s[i]!=0)
{
int f=v;
v=next[v][(int)s[i]];
if (v==0) v=newnode(),next[f][(int)s[i]]=v;
i++;
}
end[v]=now;
}
void build()
{
queue<int> q;
q.push(root);
fail[root]=root;
while(!q.empty())
{
int v=q.front();q.pop();
for(int i=0;i<128;i++)
if (next[v][i]!=0)
{
if (v==root) fail[next[v][i]]=root;
else
{
int to=fail[v];
while(to!=root)
{
if (next[to][i]==0) to=fail[to];
else break;
}
if (next[to][i]!=0) fail[next[v][i]]=next[to][i];
else fail[next[v][i]]=root;
}
q.push(next[v][i]);
}
}
}
void query()
{
int v=root,i=0;
bool flag=0;
memset(vis,0,sizeof(vis));
while(s[i]!=0)
{
while(next[v][(int)s[i]]==0&&v!=root) v=fail[v];
if (next[v][(int)s[i]]!=0)
{
v=next[v][(int)s[i]];
int to=v;
while(end[to]!=0)
{
flag=1;
vis[end[to]]=1;
to=fail[to];
}
}
i++;
}
if (flag)
{
printf("web %d:",now);
for(int i=1;i<=n;i++)
if (vis[i]) printf(" %d",i);
printf("\n");
total++;
}
}
}AC;
int main()
{
scanf("%d",&n);getchar();
AC.destroy();
for(now=1;now<=n;now++)
{
scanf("%s",s);
AC.insert();
}
scanf("%d",&m);getchar();
AC.build();
for(now=1;now<=m;now++)
{
scanf("%s",s);
AC.query();
}
printf("total: %d\n",total);
return 0;
}