HDU-1277 全文检索 AC自动机
题目给定一个非常巨大的串,然后给定许多模式串去匹配,如果是用KMP的话那么母串会被扫描很多次,这样便会超时。
AC自动机,一种对于多串匹配的优化,其原理很想KMP,只不过,在KMP算法中,next值只在于与自身的前缀进行匹配,而这里则将next的范围扩展到其他串的前缀,很NB的想法啊。哦,对了,其与KMP的区别还有一些地方,每次匹配一个字符时都搜索到根节点,看在这途中是否存在一个完整的单词。时间有限,不详写了。
代码如下:
#include <stdio.h> #include <string.h> #include <math.h> #include <queue> using namespace std; char text[60050], str[100]; int rec[10000]; struct Node { int type; Node *fail; Node *child[10]; }; void getstr( char *str ) { char c; while( c= getchar(), c< '0'|| c> '9' ) ; *( str++ )= c; while( c= getchar(), c>= '0'&& c<= '9' ) { *( str++ )= c; } *( str )= '\0'; } Node *init() { Node *r= new Node; r->type= 0; r->fail= NULL; memset( r->child, 0, sizeof( r->child ) ); return r; } void insert( Node *r, char *in, int type ) { if( *in!= '\0' ) { if( r->child[*in- '0']== NULL ) { r->child[*in- '0']= init(); } insert( r->child[*in- '0'], in+ 1, type ); } else { r->type= type; } } void creatfail( Node *r ) { queue< Node * >q; q.push( r ); while( !q.empty() ) { Node *pos= q.front(); q.pop(); for( int i= 0; i< 10; ++i ) { Node *obj= pos->fail; if( pos->child[i] ) { while( obj!= NULL ) { if( obj->child[i]!= NULL ) { pos->child[i]->fail= obj->child[i]; break; } obj=obj->fail; } if( obj== NULL ) { pos->child[i]->fail= r; } q.push( pos->child[i] ); } } } } void acauto( Node *r, char *text, int rec[], int &cnt ) { int len= strlen( text ); Node *obj= r; for( int i= 1; i< len; ++i ) { int type= text[i]- '0'; while( obj!= NULL ) { if( obj->child[type]!= NULL ) { obj= obj->child[type]; break; } obj= obj->fail; } if( obj== NULL ) { obj= r; } else { Node *temp= obj; while( temp!= r ) { if( temp->type!= 0 ) { rec[cnt++]= temp->type; temp->type= 0; } temp= temp->fail; } } } } int main() { int M, N; while( scanf( "%d %d", &M, &N )!= EOF ) { Node *r= init(); int cnt= 0; memset( text, 0, sizeof( text ) ); memset( rec, 0, sizeof( rec ) ); for( int i= 1; i<= M; ++i ) { getstr( str ); strcat( text, str ); } for( int i= 1; i<= N; ++i ) { int c; scanf( " [Key No. %d]", &c ); getstr( str ); insert( r, str, i ); } creatfail( r ); acauto( r, text, rec, cnt ); if( cnt== 0 ) { puts( "No key can be found !" ); } else { printf( "Found key:" ); for( int i= 0; i< cnt; ++i ) { printf( " [Key No. %d]", rec[i] ); } puts( "" ); } } }