【HDU】病毒侵袭持续中(AC自动机+map)

一开始一直WA,之后发现这道题不止一组输入,改成多组输入之后就过了。

利用map把每个字符串映射到它对应的结点上就行了。

11909467 2014-10-19 11:54:00 Accepted 3065 234MS 16912K 2754 B G++ KinderRiven
#include<queue>
#include<map>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 55555;
const int max_size = 130;
char ss[1111][55];
map<string,int>vis;
struct Trie{
    int next[maxn][max_size];
    int fail[maxn];
    int  val[maxn];
    int sz;
    int root;
    int num[maxn];
    int index(char e){
        return e - 31;
    }
    void init(){
        sz = 0;
        root = newnode();
    }
    int newnode(){
        val[sz] = 0; num[sz] = 0;
        memset(next[sz],-1,sizeof(next[sz]));
        sz ++;
        return sz - 1;
    }
    void insert(char *str){
        int L = strlen(str);
        int u = root;
        for(int i = 0; i < L; i++){
            int e = index(str[i]);
            if(next[u][e] == -1)
               next[u][e] = newnode();
           u = next[u][e];
        }
        val[u] = 1; //有单词
        vis[string(str)] = u;
    }
    void build(){ //建立失配边
        fail[root] = root;
        queue<int>q;
        for(int i = 0; i < max_size; 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 < max_size; 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]);
                }
            }
        }
    }
    void count(char *str){
        int now = root;
        int L = strlen(str);
        for(int i = 0; i < L; i++){
            int e = index(str[i]);
            now = next[now][e];
            int temp = now;
            while(temp != root){
                if(val[temp]){ //如果这个结点是个单词末尾
                    num[temp] ++;
                    //printf("%d\n",temp);
                }
                temp = fail[temp];
            }
        }
    }
};
Trie ac;
char _str[2222222];
int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        ac.init();
        vis.clear();
        getchar();
        for(int i = 0; i < n ; i ++){
             gets(ss[i]);
             ac.insert(ss[i]);
        }
        ac.build();
        gets(_str);
        ac.count(_str);
        for(int i = 0; i < n; i++){
            int t = vis[string(ss[i])];
            if(ac.num[t]){
                printf("%s: %d\n",ss[i],ac.num[t]);
            }
        }
    }
    return 0;
}
时间: 2024-10-25 21:41:51

【HDU】病毒侵袭持续中(AC自动机+map)的相关文章

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 <str

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的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒网站,他有着好多好多

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

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 &

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

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

hdu3065---病毒侵袭持续中(AC自动机)

Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含"英文大写字符".当然小t好想好想为民除害,但是小t从来不打没有准备的战争.知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次.大家能再帮帮他吗? Input 第

hdu3065--病毒侵袭持续中(AC自动机入门3)

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

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