hdu 3056 病毒侵袭持续中 AC自动机

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

刘汝佳的模板真的很好用,这道题直接过

学到:

cnt数组记录单词出现次数

以及map存储单词编号与字符串,便于处理相关信息

上代码:

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

const int SIGMA_SIZE=128;
const int MAXNODE = 1005*55;
const int SSIZE = 2000000+100;

struct AC
{
    int f[MAXNODE];
    int ch[MAXNODE][SIGMA_SIZE];
    int cnt[MAXNODE];
    int val[MAXNODE];
    int last[MAXNODE];
    int sz;
    void init()
    {
        memset(cnt,0,sizeof(cnt));
        memset(ch[0],0,sizeof(ch[0]));
        sz=1;
        f[0]=last[0]=val[0]=0;
    }
    inline void clear(){memset(cnt,0,sizeof(cnt));}
    void insert(string s,int v)
    {
        int u=0,n=s.size();
        for(int i=0;i<n;i++)
        {
            int c=s[i];
            if(!ch[u][c])
            {
                val[sz]=0;
                memset(ch[sz],0,sizeof(ch[sz]));
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=v;
    }
    void print(int j)
    {
        if(j)
        {
            cnt[val[j]]++;
            print(last[j]);
        }
    }
    void getfail()
    {
        queue<int>q;
        for(int c=0;c<SIGMA_SIZE;c++)
        {
            int u=ch[0][c];
            if(u){f[u]=0;q.push(u);last[u]=0;}
        }
        while(!q.empty())
        {
            int r=q.front();q.pop();
            for(int c=0;c<SIGMA_SIZE;c++)
            {
                int u=ch[r][c];
                if(!u)continue;
                q.push(u);
                int v=f[r];
                while(v && !ch[v][c])v=f[v];
                f[u]=ch[v][c];
                last[u]=val[f[u]]?f[u]:last[f[u]];
            }
        }
    }
    void find(char *T)
    {
        int n=strlen(T);
        int j=0;
        for(int i=0;i<n;i++)
        {
            int c = T[i];
            while(j && !ch[j][c])j=f[j];
            j=ch[j][c];
            if(val[j])print(j);
            else
                if(last[j])print(last[j]);
        }
    }
};

AC ac;
char str[SSIZE];
int main()
{
    //freopen("hdu3056.txt","r",stdin);
    int n;
    string word;
    while(~scanf("%d",&n))
    {
        ac.init();
        map<int, string> ms;
        for(int i=1;i<=n;i++)
        {
            cin >> word;
            ms[i]=word;
            ac.insert(word,i);
        }
        ac.getfail();
        scanf("%s",str);
        ac.find(str);
        for(int i=1;i<=n;i++)
        {
            ////////////////
            //printf("%d %d\n",i,ac.cnt[i]);
            ///////////////////
            if(ac.cnt[i])
            {
                cout << ms[i] << ": " << ac.cnt[i] << endl;
            }
        }
    }
    return 0;
}

hdu 3056 病毒侵袭持续中 AC自动机

时间: 2024-10-18 08:36:57

hdu 3056 病毒侵袭持续中 AC自动机的相关文章

HDU 3065 病毒侵袭持续中 AC自动机题解

其实本题比HDU的病毒侵袭1还简单,不过有一个陷阱卡到我了:就是搜索text的时候,当遇到的字母不是大写字母的时候,那么就要重新从根节点开始搜索,否则就会答案错误. 那么一点陷阱,居然没想到啊. 教训啊:看来对不太平常的地方,需要更加深入的思考,才能发现其中的陷阱,否则就WA了. #include <stdio.h> #include <string.h> #include <queue> using std::queue; const int MAX_N = 1001

HDU 3065 病毒侵袭持续中(AC自动机)

病毒侵袭持续中 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 15137    Accepted Submission(s): 5161 Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒网站,他有着好多好多

hdu 3065 病毒侵袭持续中 AC自动机模板题 ,,一A。

病毒侵袭持续中 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7685    Accepted Submission(s): 2687 Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒网站,他有着好多好多

HDU 3065 病毒侵袭持续中 AC自动机

HDU 3065 AC自动机 这个也可以拿来做模板了,使用静态数组模拟建树 1 //#pragma comment(linker, "/STACK:1677721600") 2 #include <map> 3 #include <set> 4 #include <stack> 5 #include <queue> 6 #include <cmath> 7 #include <ctime> 8 #include &

hdu 3056 病毒侵袭持续中 AC自己主动机

http://acm.hdu.edu.cn/showproblem.php?pid=3065 刘汝佳的模板真的非常好用,这道题直接过 学到: cnt数组记录单词出现次数 以及map存储单词编号与字符串,便于处理相关信息 上代码: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #include <st

hdu3065 病毒侵袭持续中 AC自动机入门题 N(N &lt;= 1000)个长度不大于50的模式串(保证所有的模式串都不相同), 一个长度不大于2000000的待匹配串,求模式串在待匹配串中的出现次数。

/** 题目:hdu3065 病毒侵袭持续中 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065 题意:N(N <= 1000)个长度不大于50的模式串(保证所有的模式串都不相同), 一个长度不大于2000000的待匹配串,求模式串在待匹配串中的出现次数. 思路:ac自动机做发,val标记每一个病毒串编号,通过print函数统计每一个病毒出现的次数. AC自动机好文章:http://www.cppblog.com/menjitianya/archi

hdoj 3065 病毒侵袭持续中(AC自动机)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 思路分析:问题需要模式匹配多个模式串,需要注意的是模式串会包含和重叠,需要对AC自动机的匹配过程进行修改,对于每个节点,需要从该节点的失败指针回溯, 如果失败指针回溯后的节点为某个模式串的最后一个节点,则匹配了另一个模式串: 代码如下: #include <queue> #include <cstdio> #include <cstring> #include &l

HDU 3065 病毒侵袭持续中(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065 Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含"英文大写字符".当然小t好想好想为民除害,但是小t从来不打没有准备的战争.知己知彼,百战不殆,小t首先要

HDU 3065 病毒侵袭持续中 (AC自动机)

题目链接:病毒侵袭持续中 解析:用end数组标记病毒编号,用used数组记录各个病毒出现的次数,最后对应输出即可. AC代码: #include <bits/stdc++.h> using namespace std; const int maxn = 1002; const int max_word = 52; const int max_text = 2000002; const int sigma_size = 128; char buf[max_text], vir[maxn][max