第二道AC自動機。和前面那道沒有什麼不同,都是基礎的AC自動機模板。
題目大意:
有一些病毒序列,在主串中找到所有的病毒種類即可。
求出每個網站攜帶的病毒種類。
最後輸出有多少個病毒網站。
還好輸出不坑爹!
#include<iostream>#include<cstdio>#include<string.h>#define MAX 128using 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;}