zoukankan      html  css  js  c++  java
  • HDU1277 全文检索 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( "" );
            }
        }
       
    }
    
  • 相关阅读:
    寒假学习日报20
    寒假学习日报19
    Centos firewalld开放端口
    Full GC回收详解
    JVM调优6大步骤
    JVM的方法区和永久带是什么关系?
    sql优化的几种方式
    sentinel-dashboard安装、运行(ubuntu)
    RocketMQ工作原理
    linux:nohup 不生成 nohup.out的方法
  • 原文地址:https://www.cnblogs.com/Lyush/p/2127155.html
Copyright © 2011-2022 走看看