【HDU】病毒侵袭(AC自动机模板题)

AC自动机的模板题,由于输入的字符串中的字符不保证全为小写字母,所以范围应该在130之前,而前31位字符是不可能出现在字符串的(不懂得查下ACSII表就行了),所以只需要开的结点数组大小为130足够了,如果开256就会内存超限。

11908775 2014-10-19 10:45:38 Accepted 2896 250MS 29596K 2760 B G++ KinderRiven

输入只有一组,所以不用担心超时的问题。

#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 111111;
const int max_size = 130;
const int maxd = 222;
vector<int>G[1111];
struct Trie{
    int next[maxn][max_size];
    int fail[maxn];
    int  val[maxn];
    int sz;
    int root;
    int index(char e){
        return e - 31;
    }
    void init(){
        sz = 0;
        root = newnode();
    }
    int newnode(){
        val[sz] = 0;
        memset(next[sz],-1,sizeof(next[sz]));
        sz ++;
        return sz - 1;
    }
    void insert(char *str,int pos){
        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] = pos;
        //printf("%d %d\n",u,pos);
    }
    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 pos){
        int L = strlen(str);
        int u = root;
        for(int i = 0; i < L; i++){
            int e = index(str[i]);
            u = next[u][e];
            int temp = u;
            while(temp != root){
                if(val[temp] != 0)
                    G[pos].push_back(val[temp]);
                temp = fail[temp];
            }
        }
        return;
    }
};
Trie ac;
int main(){
    int n,m;
    ac.init();
    scanf("%d",&n);
    for(int i = 1; i <= n; i++){
        char str[maxd];
        scanf("%s",str);
        ac.insert(str,i);
    }
    //printf("%d\n",ac.sz);
    ac.build();
    scanf("%d",&m);
    for(int i  = 1; i <= m; i++){
        char str[maxn];
        scanf("%s",str);
        ac.count(str,i);
    }
    int cnt = 0;
    for(int i = 1; i <= m; i++)if(G[i].size()){
        sort(G[i].begin(),G[i].end());
        cnt ++;
        printf("web %d:",i);
        for(int j = 0; j < G[i].size(); j++)
            printf(" %d",G[i][j]);
        printf("\n");
    }
    printf("total: %d\n",cnt);
}
时间: 2024-10-05 12:51:06

【HDU】病毒侵袭(AC自动机模板题)的相关文章

HDU 2222(AC自动机模板题)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 题目大意:多个模式串.问匹配串中含有多少个模式串.注意模式串有重复,所以要累计重复结果. 解题思路: AC自动机模板题. 一开始使用LRJ的坑爹静态模板,不支持重复的模式串. 在做AC自动机+DP的时候,扒了zcwwzdjn大神的动态优化(失配指向root)写法,以及借鉴了网上的AC自动机模板, 搞出了这么一个支持重复串的模板. #include "cstdio" #include

HDU 2222 (AC自动机模板题)

题意: 给一个文本串和多个模式串,求文本串中一共出现多少次模式串 分析: ac自动机模板,关键是失配函数 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string&g

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

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

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 2222 AC自动机模板题

题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 using namespace std; 5 char key[55]; 6 char des[1111111]; 7 struct node{ 8 node *fail; 9 node *next[26]; 10 int cnt;

HDU 3065 (AC自动机模板题)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 题目大意:多个模式串,范围是大写字母.匹配串的字符范围是(0~127).问匹配串中含有哪几种模式串,且每种模式串出现了多少次. 解题思路: AC自动机模板题.模式串的范围是大写字母,但是匹配串的范围却是(0~127). 如果Trie 开到 128 加上不回收内存,就会MLE. 实际上开到26就行了,find的时候对于c<0||c>26,强制令pos=root出现失配,并开始下一个字符就行了

HDU 2896 (AC自动机模板题)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896 题目大意:多个模式串.多个匹配串.其中串的字符范围是(0~127).问匹配串中含有哪几个模式串. 解题思路: AC自动机模板题.注意一下字符范围. cnt记录这个模式串的个数改为这个模式串的index. find的时候,把找到的index压入vector里面即可. 注意有多个匹配串,每次find之后会把last->cnt修改,原因是防止一个模式串出现了多次被压入vector,所以先备份一下,