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( "" );
        }
    }
   
}
posted @ 2011-08-04 12:05  沐阳  阅读(382)  评论(0编辑  收藏  举报