病毒侵袭---hdu2896(AC自动机)

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

输入的字符是所有可见的ASCII码(共有127个)所以要注意一下;

把结果存到一个数组中,然后输出;

要用c++交,G++会MLE的;

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;

const int N = 1e4+10;
int vis[N], a[N], cnt;
char s[N];
struct node
{
    int leaf;
    node *next[127],*fail;
};

void AddTrie(char s[], node *root, int num)
{
    node *p = root;
    for(int i=0; s[i]; i++)
    {
        int k = (int)s[i];
        if(p->next[k]==NULL)
            p->next[k] = new node();
        p = p->next[k];
    }
    p->leaf = num;
}
void GetFail(node *root)
{
    node *p, *q;
    queue<node*>Q;
    Q.push(root);
    while(Q.size())
    {
        p = Q.front(); Q.pop();
        for(int i=0; i<127; i++)
        {
            if(p->next[i]!=NULL)
            {
                q = p->fail;
                while(q!=NULL)
                {
                    if(q->next[i]!=NULL)
                    {
                        p->next[i]->fail = q->next[i];
                        break;
                    }
                    q = q->fail;
                }
                if(q==NULL)
                    p->next[i]->fail = root;
                Q.push(p->next[i]);
            }
        }
    }
}

void Query(char s[], node *root)
{
    node *p = root, *q;
    for(int i=0; s[i]; i++)
    {
        int k = (int)s[i];

        while(p->next[k] == NULL && p!=root)///如果匹配不成功,那么就走失败路径,沿着fail指针走,一直到找到或者跟结点为止;
            p = p->fail;
        p = p->next[k];
        if(p==NULL)
            p = root;
        q = p;
        while(q!=root)
        {
            if(q->leaf && !vis[q->leaf])
            {
                a[cnt++] = q->leaf;
                vis[q->leaf] = 1;
            }
            q = q->fail;
        }
    }
}
void FreeTrie(node *root)
{
    node *p = root;
    for(int i=0; i<127; i++)
    {
        if(p->next[i]!=NULL)
            FreeTrie(p->next[i]);
    }
    free(p);
}
int main()
{
    int n, m;
    while(scanf("%d", &n)!=EOF)
    {
        node *root = new node();
        for(int i=1; i<=n; i++)
        {
            scanf("%s", s);
            AddTrie(s, root, i);
        }
        GetFail(root);
        scanf("%d", &m);
        int ans = 0;
        for(int i=1; i<=m; i++)
        {
            scanf("%s", s);
            memset(a, 0, sizeof(a));
            memset(vis, 0, sizeof(vis));
            cnt = 0;
            Query(s, root);
            if(cnt)
            {
                ans++;
                printf("web %d:", i);
                sort(a, a+cnt);
                for(int j=0; j<cnt; j++)
                    printf(" %d", a[j]);
                printf("\n");
            }
        }
        printf("total: %d\n", ans);
        FreeTrie(root);
    }
    return 0;
}

时间: 2024-10-07 00:27:44

病毒侵袭---hdu2896(AC自动机)的相关文章

HDU2896病毒侵袭(ac自动机)

网上很多代码都略显繁琐,看了一下yy dalao的代码感觉很好,但他懒得打题解(好吧我也是 以0为根节点的话,我把yy的一段代码删了改用fail[c]=x==0?0:ch[fail[x]][i];来实现特判,效果还不错! 也算是AC自动机的模版题吧,用了一个id数组来储藏每一个特征码的最后一个字符所在位置,再用vis来看网站源码中有哪条特征码(即哪条特征码的id被访问到 #include<cstdio> #include<cstring> using namespace std;

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

题目链接:病毒侵袭 解析:利用end数组记录各病毒的编号,然后统计即可.注意此时sigma_size为128(0~127的ascii码可见字符). AC代码: #include <bits/stdc++.h> using namespace std; const int maxn = 502; const int max_word = 202; const int max_text = 10002; const int sigma_size = 128; struct Trie{ int ne

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年一遇的世界奇观,那是多么幸福的事

HDOJ 题目2896 病毒侵袭(AC自动机)

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

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 思路分析:题目为模式匹配问题,对于一个给定的字符串,判断能匹配多少个模式:该问题需要静态建树,另外需要对AC自动机的模板加以修改, 对于每个匹配的模式的最后一个单词的fail指针指向root,即可实现一个字符串进行多次模式匹配: 代码如下: #include <queue> #include <cstdio> #include <cstring> #include &

【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&

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

传送门 病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)            Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 63941             Accepted Submission(s): 21264 Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一

HDU2896 病毒侵袭【AC自动机】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896 题目大意: 给你N个模式串(编号为1~N).接下来给你M个主串.问:主串中出现的模式串的编号. 思路: 和HDU2222一样.都是求文本串(主串)中出现的模式串.不同的是这道题要求输出的是模式 串的编号.用Val[]来保存模式串的编号id.同时注意字符为ASCII码可见字符,即32~127共 95个.其实定义95就可以了,我这里定义了128,不过没什么影响. AC代码: #include<i

病毒侵袭(AC自动机变形)

Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒.小t不幸成为受害者之一.小t如此生气,他决定要把世界上所有带病毒的网站都找出来.当然,谁都知道这是不可能的.小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了).万事开头难,小t收集了

HDU - 2896 病毒侵袭 (AC自动机,last优化)

题目链接:HDU - 2896 题意:给你n个模式串,对应每个模式串由编号,给出m个文本串,然后你要输出对应所匹配出模式串序号,以及有多少个文本串中有模式串 思路:比起比较基本统计个数,这里我们可以用set或者map来统计模式串序号 这里总结一下新学习的last优化. 参考博客:(1) last相当于一个超级fail指针: 因为我们只有到根节点时才会重新匹配一个字母,所以我们此时直接记录一个last ,直接结束当前匹配过程.直接省去原 Fail 指针到可以匹配的节点之间的距离. 同时结合路径压缩