hdoj 2896 病毒侵袭(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896

思路分析:题目为模式匹配问题,对于一个给定的字符串,判断能匹配多少个模式;该问题需要静态建树,另外需要对AC自动机的模板加以修改,

对于每个匹配的模式的最后一个单词的fail指针指向root,即可实现一个字符串进行多次模式匹配;

代码如下:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int KIND = 128;
const int MAX_NODE = 300 * 500;
const int MAX_M = 10000 + 100;
char str[MAX_M];
int vir_match[MAX_M];

struct Trie {
    int root, count;
    int next[MAX_NODE][KIND], fail[MAX_NODE], end[MAX_NODE];
    void Init()
    {
        count = 0;
        root = NewNode();
    }
    int NewNode()
    {
        for (int i = 0; i < KIND; ++i)
            next[count][i] = -1;
        end[count] = -1;
        return count++;
    }

    void Insert(char *str, int id)
    {
        int i = 0, k = 0;
        int now = root;

        while (str[i])
        {
            k = str[i];
            if (next[now][k] == -1)
                next[now][k] = NewNode();
            now = next[now][k];
            ++i;
        }
        end[now] = id;
    }

    void BuildAutomaton()
    {
        queue<int> Q;

        fail[root] = -1;
        Q.push(root);
        while (!Q.empty())
        {
            int now = Q.front();
            int p = -1;
            Q.pop();

            if (end[now] != -1)
                fail[now] = root;
            for (int i = 0; i < KIND; ++i)
            {
                if (next[now][i] != -1)
                {
                    if (now == root)
                        fail[next[now][i]] = root;
                    else
                    {
                        p = fail[now];
                        while (p != -1)
                        {
                            if (next[p][i] != -1)
                            {
                                fail[next[now][i]] = next[p][i];
                                break;
                            }
                            p = fail[p];
                        }
                        if (p == -1)
                            fail[next[now][i]] = root;
                    }
                    Q.push(next[now][i]);
                }
            }
        }
    }

    int Match(char *str)
    {
        int i = 0, k = 0, vir_count = 0;
        int p = root;

        while (str[i])
        {
            k = str[i];
            while (next[p][k] == -1 && p != root)
                p = fail[p];
            p = next[p][k];
            p = (p == -1) ? root : p;

            if (end[p] != -1)
            {
                vir_match[vir_count++] = end[p];
                p = fail[p];
            }
            ++i;
        }
        return vir_count;
    }
};

Trie root;

int main()
{
    int vir_num = 0, web_num = 0;
    int match_count = 0, web_matched = 0;

    while (scanf("%d\n", &vir_num) != EOF)
    {
        root.Init();
        for (int i = 0; i < vir_num; ++i)
        {
            gets(str);
            root.Insert(str, i + 1);
        }

        web_matched = 0;
        match_count = 0;
        root.BuildAutomaton();
        scanf("%d\n", &web_num);
        for (int i = 0; i < web_num; ++i)
        {
            int ans = 0;

            gets(str);
            ans = root.Match(str);
            sort(vir_match, vir_match + ans);
            if (ans)
            {
                web_matched++;
                printf("web %d: ", i + 1);
                for (int j = 0; j < ans - 1; ++j)
                    printf("%d ", vir_match[j]);
                printf("%d\n", vir_match[ans - 1]);
            }
        }
        printf("total: %d\n", web_matched);
    }
    return 0;
}
时间: 2024-12-26 11:49:42

hdoj 2896 病毒侵袭(AC自动机)的相关文章

HDU 2896 病毒侵袭 AC自动机题解

本题是在text里面查找key word的增强版,因为这里有多个text. 那么就不可以简单把Trie的叶子标志记录修改成-1进行加速了,可以使用其他技术,我直接使用个vis数组记录已经访问过的节点,达到加速效果,速度还算挺快的. 不过看discuss里面有人直接使用Trie,做出了140ms的速度,而且他的程序严格来说并不正确,可见本题的数据很水啊.Trie的时间效率肯定比AC自动机低,但是在数据很水的特殊情况下,Trie的速度也可以很快的. 注意两个细节: 1 病毒也需要安装顺序输出,不小心

hdu 2896 病毒侵袭 AC自动机(查找包含哪些子串)

病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 19465    Accepted Submission(s): 4814 Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿

[hdu 2896] 病毒侵袭 [ac自动机][病毒特征码匹配]

病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 20728    Accepted Submission(s): 5058 Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋--我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事

HDU 2896 病毒侵袭 (AC自动机模板)

病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 13063    Accepted Submission(s): 3378 Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋--我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事

HDU 2896 病毒侵袭(AC自动机模版题)

AC自动模版题,中文题目就不叙述题意了啊. AC自动主要是构造出字典树之后找到fail指针的跳转,类似于KMP里面的next数组的跳转啊,注意这里是多模式跳转.意思就是这个串跳到下一个串的什么位置啊. 先帖一下,做多了再一起总结吧. 病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 11347    Accepted Submi

HDU 2896 病毒侵袭(AC自动机)

解题思路: 对AC自动机算法的理解和应用,要注意的是,题目中的字符是128个ASCII码,而不是常用的26个英文字符,因此子节点的数目为128. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <vector> #include &

hdoj 2896 病毒侵袭 【AC自动机 基础题】

病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 15893    Accepted Submission(s): 4055 Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋--我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事

hdu2896 病毒侵袭 ac自动机

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2896 题目: 病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 23013    Accepted Submission(s): 5551 Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大

hdu2896 病毒侵袭 AC自动机入门题 N(N &lt;= 500)个长度不大于200的模式串(保证所有的模式串都不相同), M(M &lt;= 1000)个长度不大于10000的待匹配串,问待匹配串中有哪几个模式串,

/** 题目:hdu2896 病毒侵袭 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 题意:N(N <= 500)个长度不大于200的模式串(保证所有的模式串都不相同), M(M <= 1000)个长度不大于10000的待匹配串,问待匹配串中有哪几个模式串, 题目保证每个待匹配串中最多有三个模式串. 思路:ac自动机做法,字符为可见字符,那么直接就是他们的ascii值作为每一个字符的标志.最多128: 由于不超过三个,所以找到3个就可以re