HDU2222 Keywords Search【AC自动机】

题目链接:

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;
}
时间: 2024-08-04 17:30:27

HDU2222 Keywords Search【AC自动机】的相关文章

hdu2222 Keywords Search ac自动机

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 题目: Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 56558    Accepted Submission(s): 18493 Problem Description In the mo

hdu2222 Keywords Search &amp; AC自动机学习小结

传送门:http://http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:AC自动机入门题,直接上AC自动机即可. 对于构建AC自动机,我们要做的只有三件事: 1)构建字典树 2)构建失败指针 3)构建trie图(这道题好像不做这一步也能A...但是这一步不做是会被卡成O(n^2)的...) 1)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

HDU 2222 Keywords Search AC自动机入门题

单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自动机的基础: 1 Trie, 以这个数据结构为基础的,不过增加一个fail指针和构造fail的函数 2 KMP,不是直接运用KMP,而是需要KMP的思想,KMP思想都没有的话,理解这个算法会更加吃力的. 注意本题的单词会有重复出现的,一个单词只能统计一次. 搜索了一下网上的题解,发现好多代码都是一大抄的啊,⊙﹏⊙b汗. 本博客的乃是原创代码,代码风格也是差不多固定的,转载请注明出处:http://blog.c

[hdu2222] [AC自动机模板] Keywords Search [AC自动机]

AC自动机模板,注意!ch,Fail,lab数组的大小不是n而是节点个数,需要认真计算! 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <ctime> 7 #include <cstdlib> 8 #include <queue>

HDU 2222 Keywords Search AC自动机

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 67122    Accepted Submission(s): 22584 Problem Description In the modern time, Search engine came into the life of everybody lik

hdu 2222 Keywords Search(ac自动机入门题)

1 /************************************************************ 2 题目: Keywords Search(hdu 2222) 3 链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 4 算法: ac自动机 5 算法思想: 多个字符串匹配,也就是相当于多个kmp 6 ***********************************************************

HDU 2222 Keywords Search (AC自动机入门 模板)

AC自动机入门 Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.学习AC自动机之前得先有Trie树和KMP模式匹配算法的基础. AC自动机算法分为3步:1.构造一棵tire树  2.构造失败指针  3.进行模式匹配 AC自动机的优化:Trie图 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other

HDU 2222 Keywords Search (AC自动机模板题)

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 67950    Accepted Submission(s): 22882 Problem Description In the modern time, Search engine came into the life of everybody lik

Match:Keywords Search(AC自动机模板)(HDU 2222)

多模匹配 题目大意:给定很多个字串A,B,C,D,E....,然后再给你目标串str字串,看目标串中出现多少个给定的字串. 经典AC自动机模板题,不多说. 1 #include <iostream> 2 #include <algorithm> 3 #include <functional> 4 #include <string.h> 5 #define MAX 26 6 7 using namespace std; 8 9 struct node 10 {

hdoj 2222 Keywords Search(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路分析:该问题为多模式匹配问题,使用AC自动机解决:需要注意的问题是如何统计该待查询的字符串包含的关键字: 假设待查找的字符串为str[0..n],则str[i…j]可能为某一个关键字:假设当前正在匹配字符str[k],则以str[i..k]为关键字的所有可能 可能的关键字的最后一个字符为str[k],使用fail指针进行跳转并判断以str[k]结尾的该结点是否为关键字最后一个结点,重复进行