第二道AC自动机。和前面那道没有什么不同,都是基础的AC自动机模板。
题目大意:
有一些病毒序列,在主串中找到所有的病毒种类即可。
求出每个网站携带的病毒种类。
最后输出有多少个病毒网站。
还好输出不坑爹!
#include<iostream>
#include<cstdio>
#include<string.h>
#define MAX 128
using namespace std;
struct node
{
int id,fail,next[MAX];
void init(){
memset( next,0,sizeof(next) );
fail=-1,id=0;
}
}Tire[111111];
int root,tot;
int queue[111111];
char str[11111];
int N,M;
void init(){
root=tot=0;
Tire[root].init();
}
void insert( int id,char *s )
{
int i=0,k;
int p=root;
while( s[i] )
{
k=s[i++];
if( !Tire[p].next[k] )
{
Tire[++tot].init();
Tire[p].next[k]=tot;
}
p=Tire[p].next[k];
}
Tire[p].id=id;
}
void build_ac_automation()
{
int head,tail;
head=tail=0;
queue[tail++]=root;
while( head<tail )
{
int cur=queue[head++];
for( int i=0;i<MAX;i++ )
{
if( Tire[cur].next[i] )
{
int son=Tire[cur].next[i];
int p=Tire[cur].fail;
if( cur==root )
Tire[son].fail=root;
else
Tire[son].fail=Tire[p].next[i];
queue[tail++]=son;
}
else
{
int p=Tire[cur].fail;
if( cur==root )
Tire[cur].next[i]=root;
else
Tire[cur].next[i]=Tire[p].next[i];
}
}
}
}
int query( char *s,int web )
{
int i=0,k;
int p=root,vis[555];
bool found=false;
memset( vis,0,sizeof(vis) );
while( s[i] )
{
k=s[i++];
while( !Tire[p].next[k]&&p!=root )
p=Tire[p].fail;
p=Tire[p].next[k];
if(p==-1)p=0;
int temp=p;
while( temp!=root )
{
if( Tire[temp].id>0 )
found=true;
vis[Tire[temp].id]=1;
temp=Tire[temp].fail;
}
}
int cnt=0;
if( found )
{
printf( "web %d:",web );
for( int i=1;i<=N;i++ )
if( vis[i] )
printf( " %d",i ),cnt++;
printf( "\n" );
}
return cnt;
}
int main()
{
while( scanf( "%d\n",&N )!=EOF )
{
init();
for( int i=1;i<=N;i++ )
{
gets(str);
insert(i,str);
}
build_ac_automation();
scanf( "%d\n",&M );
int total=0;
for( int i=1;i<=M;i++ )
{
gets(str);
if( query(str,i) )
total++;
}
printf( "total: %d\n",total );
}
return 0;
}