题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2896
题解:
AC自动机裸题。值得注意的是:这里会很容易爆内存,并且结果是从小到大输出。
代码:
#include <cmath>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
const int maxn1 = 200+10;
const int maxn2 = 10000+10;
char keyword[maxn1];
char checkword[maxn2];
int ans[maxn2];
struct node
{
int cnt;
int terminal;
node *next[130],*fail;
node()
{
cnt=0;
terminal=0;
fail=NULL;
for(int i=0;i<130;i++)
next[i]=0;
}
}*root;
void insert(char *s,node *p,int id)
{
int i=0,k;
while(s[i])
{
k=s[i++];
if(p->next[k]==NULL)
p->next[k]=new node();
p=p->next[k];
}
p->cnt=id;
p->terminal=1;
}
void build(node *root)
{
queue<node*>q;
root->fail=NULL;
q.push(root);
node *temp,*p;
while(!q.empty())
{
temp=q.front();
q.pop();
for(int i=0;i<130;i++)
{
if(temp->next[i])
{
if(temp==root)
temp->next[i]->fail=root;
else
{
p=temp->fail;
while(p)
{
if(p->next[i])
{
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(!p)
temp->next[i]->fail=root;
}
q.push(temp->next[i]);
}
}
}
}
int query(char *s,node *root,int id)
{
int sum=0,len=(int)strlen(s),k;
node *p=root;
for(int i=0;i<len;i++)
{
k=s[i];
while(!p->next[k]&&p!=root)
p=p->fail;
p=p->next[k];
if(!p)
p=root;
node *temp=p;
while(temp!=root&&temp->cnt)
{
ans[sum]=temp->cnt;
sum+=p->terminal;
temp=temp->fail;
}
}
return sum;
}
void del(node *root)
{
if(root==NULL)
return;
for(int i=0;i<130;i++)
del(root->next[i]);
delete(root);
}
int main()
{
root=new node();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",keyword);
insert(keyword,root,i);
}
int cnt=0;
int m;
build(root);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",checkword);
int judge=query(checkword, root, i);
bool flag=false;
if(judge)
{
flag=true;
printf("web %d:",i);
sort(ans,ans+judge);
for(int j=0;j<judge;j++)
printf(" %d",ans[j]);
printf("\n");
}
if(flag)
cnt++;
}
printf("total: %d\n",cnt);
}