zoukankan      html  css  js  c++  java
  • 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
    ", &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
    ", &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
    ", vir_match[ans - 1]);
                }
            }
            printf("total: %d
    ", web_matched);
        }
        return 0;
    }
  • 相关阅读:
    c++读取文本文件
    C++在设计和使用智能指针
    spring mvc 控制器方法传递一些经验对象的数组
    unity3D实际的原始视频游戏开发系列讲座10它《战斗:外来入侵》在第一季度游戏开发
    Docker安装应用程序(Centos6.5_x64)
    VC和gcc在保证功能static对线程安全的差异变量
    POJ 1252 Euro Efficiency
    extjs_03_grid(添加数据)
    BZOJ 1212 HNOI2004 L语言 AC自己主动机(Trie树)+动态规划
    OpenGL开发时,fatal error C1083: 无法打开包括文件:“glglut.h”: No such file or directory
  • 原文地址:https://www.cnblogs.com/tallisHe/p/4665957.html
Copyright © 2011-2022 走看看