一开始,节点用了map库,map库的会比一般用数组的表示法慢5倍以上(可见字符总共130个,log2(130)>6),所以,确定内存不会爆的话,就普通实现吧
#include <iostream>
#include <cstdio>
#include <cstring>
#include <deque>
#define CNUM 132
#define LMT 10005
using namespace std;
struct node
{
node *chl[CNUM];
node *fail;
int aim;
node():aim(0),fail(0)
{
memset(chl,0,sizeof(chl));
}
};
char sec[LMT];
node *root;
deque<node *>q;
bool dudu[502];
void insert(char src[],int sign)
{
int len=strlen(src),index;
node *current=root;
for(int i=0;i<len;i++)
{
index=src[i];
if(current->chl[index])current=current->chl[index];
else
{
current->chl[index]=new node;
current=current->chl[index];
}
}
current->aim=sign;
}
void build_ac(void)
{
node *current,*tem;
q.clear();
q.push_back(root);
while(!q.empty())
{
current=*q.begin();
q.pop_front();
for(int i=0;i<CNUM;i++)
if(current->chl[i])
{
if(current==root)current->chl[i]->fail=root;
else
{
tem=current->fail;
while(tem)
{
if(tem->chl[i])
{
current->chl[i]->fail=tem->chl[i];
break;
}
tem=tem->fail;
}
if(!tem)current->chl[i]->fail=root;
}
q.push_back(current->chl[i]);
}
}
}
bool equry(void)
{
int index,ret=0,len=strlen(sec);
node *current=root,*tem;
memset(dudu,0,sizeof(dudu));
for(int i=0;i<len;i++)
{
index=sec[i];
while(current&¤t->chl[index]==NULL)
current=current->fail;
if(!current)current=root;
else current=current->chl[index];
tem=current;
while(tem!=root&&!dudu[tem->aim])
{
if(tem->aim)
{
ret=1;
dudu[tem->aim]=1;
}
tem=tem->fail;
}
}
return ret;
}
void kill(node *x)
{
for(int i=0;i<CNUM;i++)
if(x->chl[i])kill(x->chl[i]);
delete x;
}
int main(void)
{
int n,m,ans;
char str[1002];
while(~scanf("%d",&n))
{
root=new node;
for(int i=1;i<=n;i++)
{
scanf("%s",str);
insert(str,i);
}
scanf("%d",&m);
build_ac();ans=0;
for(int i=1;i<=m;i++)
{
scanf("%s",sec);
if(equry())
{
ans++;
printf("web %d:",i);
for(int i=1;i<=n;i++)
if(dudu[i])printf(" %d",i);
printf("\n");
}
}
printf("total: %d\n",ans);
kill(root);
}
return 0;
}