题意:中文题意
做法:AC自动机,注意的事项在代码中
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#define maxs 128
#define MME(i,j) memset(i,j,sizeof(i))
using namespace std;
struct Trie{
int nexts[210*500][maxs],fail[210*500],ends[210*500];
int root,L;
int newnode(){
MME(nexts[L],-1);
ends[L++]=-1;
return L-1;
}
void init(){
L=0;
root=newnode();
}
void Insert(char *s,int id){
int len=strlen(s),now=root;
for(int i=0;i<len;i++)
{
if(nexts[now][s[i]] == -1)//当前节点的第i个儿子不存在
nexts[now][s[i]]=newnode();
now=nexts[now][s[i]];
}
ends[now]=id;
}
void build(){
queue<int> q;
fail[root]=root;
for(int i=0;i<maxs;i++){
if(nexts[root][i] == -1)//当前根节点的 第i个儿子不存在时全部指向了根
nexts[root][i]=root;
else{
fail[nexts[root][i]]=root;
q.push(nexts[root][i]);
}
}
int now;
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=0;i<128;i++)
if(nexts[now][i] == -1 )
nexts[now][i]=nexts[fail[now]][i];
else{
fail[nexts[now][i]]=nexts[fail[now]][i];
q.push(nexts[now][i]);
}
}
}
bool used[510];
bool query(char *s,int n,int id)
{
int temp,len=strlen(s),now=root;
MME(used,0);
bool flag=0;
for(int i=0;i<len;i++){
now=nexts[now][s[i]];
temp=now;
while(temp!=root){
if(ends[temp]!=-1)
{
used[ends[temp]]=1;
flag=1;
}
temp=fail[temp];
}
}
if(flag==false)
return 0;
printf("web %d:",id);
for(int i=1;i<=n;i++)
{
if(used[i])
printf(" %d",i);
}
puts("");
return 1;
}
};//AC自动机 模板,query函数需要根据题意来修改。
char keyword[10010];
Trie ac;
int main()
{
int n,m;
while(~scanf("%d",&n)){
ac.init();
for(int i=1;i<=n;i++)
{
scanf("%s",keyword);
ac.Insert(keyword,i);
}
ac.build();
int ans=0;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",keyword);
if(ac.query(keyword,n,i))
ans++;
}
printf("total: %d\n",ans);
}
return 0;
}