码迷,mamicode.com
首页 > 其他好文 > 详细

HDU2222 Keywords Search【AC自动机】

时间:2015-05-23 00:05:07      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

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


题目大意:

给你N个模式串,和一个文本串。问:文本串中共出现了几个模式串。


思路:

这道题是AC自动机的基础题目。就是求文本串中出现的模式串个数。用Val[]数组来标记模式串。

最后用ans累加模式串个数。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 500010;
const int SIZE = 26;
struct Trie
{   //Next[i][j]表示字典中i节点的字符为j的儿子节点编号
    int Next[MAXN][SIZE];
    int Fail[MAXN]; //失配数组  
    int Val[MAXN];  //标记模式串
    int root,L;     //L为节点编号
    int NewNode()   
    {
        for(int i = 0; i < 26; ++i)
            Next[L][i] = -1;
        Val[L++] = 0;
        return L-1;
    }
    void Init()
    {
        L = 0;
        root = NewNode();
    }
    void Insert(char *Buf)
    {
        int len = strlen(Buf);
        int now = root;
        for(int i = 0; i < len; ++i)
        {
            if(Next[now][Buf[i]-'a'] == -1)
                Next[now][Buf[i]-'a'] = NewNode();
            now = Next[now][Buf[i]-'a'];
        }
        Val[now]++; //在模式串末尾标记
    }
    void Build()    //构造AC自动机
    {
        queue<int> Q;
        Fail[root] = root;
        for(int i = 0; i < 26; ++i)
        {
            if(Next[root][i] == -1)
                Next[root][i] = root;
            else
            {
                Fail[Next[root][i]] = root;
                Q.push(Next[root][i]);
            }
        }
        while( !Q.empty() )
        {
            int now = Q.front();
            Q.pop();
            for(int i = 0; i < 26; ++i)
            {
                if(Next[now][i] == -1)
                    Next[now][i] = Next[Fail[now]][i];
                else
                {
                    Fail[Next[now][i]] = Next[Fail[now]][i];
                    Q.push(Next[now][i]);
                }
            }
        }
    }
    int Query(char *Buf)    
    {
        int len = strlen(Buf);
        int now = root;
        int res = 0;    //计算模式串出现个数
        for(int i = 0; i < len; ++i)
        {
            now = Next[now][Buf[i]-'a'];
            int temp = now;
            while(temp != root)
            {
                res += Val[temp];
                Val[temp] = 0;
                temp = Fail[temp];
            }
        }
        return res;
    }
    
//    void Debug()
//    {
//        for(int i = 0; i < L; ++i)
//        {
//            printf("id = %3d,Fail = %3d,Val = %3d,chi = [",i,Fail[i],Val[i]);
//            for(int j = 0; j < 26; ++j)
//                printf("%2d",Next[i][j]);
//            printf("]\n");
//        }
//    }

};
char Buf[MAXN<<1];
Trie AC;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int N;
        scanf("%d",&N);
        AC.Init();
        for(int i = 0; i < N; ++i)
        {
            scanf("%s",Buf);
            AC.Insert(Buf);
        }
        AC.Build();
        scanf("%s",Buf);
        printf("%d\n",AC.Query(Buf));
    }

    return 0;
}




HDU2222 Keywords Search【AC自动机】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/45921149

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!