您的位置:首页 > 编程语言 > C语言/C++

AC自动机

2013-09-20 16:16 411 查看
http://www.cnblogs.com/Lyush/archive/2011/09/04/2165975.html

题目 http://acm.hdu.edu.cn/showproblem.php?pid=2222

#include <cstring>

#include <cstdio>

#include <cstdlib>

#include <queue>

using namespace std;

struct Node

{

    int end;

    Node *fail, *child[26];

};

char s[1000005];

void getstr( char *s )

{

    char c;

    int p = 0;

    while( c = getchar(), c == ' ' || c == '\n' ) ;

    s[p++] = c;

    while( c = getchar(), c != ' ' && c != '\n' )

        s[p++] = c;

    s[p] = '\0';

}

Node *init(  )

{

    Node *r = ( Node * )malloc( sizeof( Node ) );

    r->end = 0;

    r->fail = NULL;

    memset( r->child, NULL, sizeof( r->child ) );

    return r;

}

void creattree( Node *p, char *in )

{

    int index = *in - 'a';

    if( p->child[index] == NULL )

        p->child[index] = init();

    if( *( in + 1 ) )

        creattree( p->child[index], in + 1 );

    else

        p->child[index]->end++;

}

void creatfail( Node *p )

{

    queue< Node * >q;

    q.push( p );

    while( !q.empty() )

    {

        Node *pos = q.front();

        q.pop();

        for( int i = 0; i < 26; ++i )

        {

            Node *f = pos->fail;

            if( pos->child[i] )

            {

                while( f != NULL )

                {

                    if( f->child[i] )

                    {

                        pos->child[i]->fail = f->child[i];

                        break;

                    }

                    else

                        f = f->fail;

                }

                if( f == NULL )

                {

                    pos->child[i]->fail = p;

                }

                q.push( pos->child[i] );

            }

        }

    }

}

int acauto( Node *p, char *text )

{

    int ans = 0, lenth = 0, len = strlen( text );

    Node *f = p;

    for( int i = 0; i < len; ++i )

    {

        int type = text[i] - 'a';

        while( f )

        {

            if( f->child[type] )

            {

                f = f->child[type];

                break;

            }

            else

                f = f->fail;

        }

        if( f == NULL ) // 如果都已经找到了根节点仍不匹配

        {

            f = p; // 从头开始

            continue;

        }

        Node *t = f;

        while( t != p ) // 成功匹配一个字符的更新操作

        {

            if( t->end )

            {

                ans += t->end;

                t->end = 0;

            }

            t = t->fail;

        }

    }

    return ans;

}

void _free( Node *p )

{

    for( int i = 0; i < 26; ++i )

    {

        if( p->child[i] )

            _free( p->child[i] );

    }

    free( p );

}

int main()

{

    int T;

    scanf( "%d\n", &T );

    while( T-- )

    {

        int N;

        Node *p = init();

        scanf( "%d", &N );

        for( int i = 0; i < N; ++i )

        {

            getstr( s );

            creattree( p, s );

        }

        getstr( s );

        creatfail( p );

        printf( "%d\n", acauto( p, s ) );

    }

}

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