您的位置:首页 > 其它

HDU-1277 全文检索 AC自动机

2011-08-04 12:05 387 查看
  题目给定一个非常巨大的串,然后给定许多模式串去匹配,如果是用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( "" );
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: