HDU3065(AC自动机入门题)

病毒侵袭持续中

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9831    Accepted Submission(s): 3457

Problem Description

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

Input

第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。

Output

按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。

Sample Input

3

AA

BB

CC

ooxxCC%dAAAoen....END

Sample Output

AA: 2

CC: 1

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=500005;
const int N=128;
int n;
int Hash[1005];
struct ID{
    char ss[55];
    ID()
    {
        memset(ss,0,sizeof(ss));
    }
}words[1005];
struct Trie{
    int next[MAXN][N],fail[MAXN],end[MAXN];
    int tot,root,id;
    int newnode()
    {
        for(int i=0;i<N;i++)
            next[tot][i]=-1;
        end[tot++]=0;
        return tot-1;
    }

    void init()
    {
        tot=0;
        root=newnode();
    }

    void insert(char buf[],int id)
    {
        int len=strlen(buf);
        int now=root;
        for(int i=0;i<len;i++)
        {
            int k=buf[i];
            if(next[now][k]==-1)
                next[now][k]=newnode();
            now=next[now][k];
        }
        end[now]=id;
    }

    void build()
    {
        fail[root]=root;
        queue<int> que;
        for(int i=0;i<N;i++)
            if(next[root][i]==-1)
                next[root][i]=root;
            else
            {
                fail[next[root][i]]=root;
                que.push(next[root][i]);
            }

        while(!que.empty())
        {
            int now=que.front();
            que.pop();

            for(int i=0;i<N;i++)
                if(next[now][i]==-1)
                    next[now][i]=next[fail[now]][i];
                else
                {
                    fail[next[now][i]]=next[fail[now]][i];
                    que.push(next[now][i]);
                }
        }
    }

    void query(char buf[])
    {
        int len=strlen(buf);
        int now=root;
        for(int i=0;i<len;i++)
        {
            now=next[now][buf[i]];
            int temp=now;
            while(temp!=root)
            {
                if(end[temp]!=0)
                    Hash[end[temp]]++;
                //若每个模式串只在主串中匹配一次则加上 end[temp]=0;
                temp=fail[temp];
            }
        }

        for(int i=1;i<=n;i++)
        {
            if(Hash[i]!=0)
            {
                printf("%s: %d\n",words[i].ss,Hash[i]);
            }
        }
    }
};
Trie ac;
char buf[2000005];
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(Hash,0,sizeof(Hash));
        ac.init();
        for(int i=1;i<=n;i++)
        {
            scanf("%s",words[i].ss);
            ac.insert(words[i].ss,i);
        }
        ac.build();
        scanf("%s",buf);
        ac.query(buf);
    }
    return 0;
}
时间: 2024-10-12 17:09:52

HDU3065(AC自动机入门题)的相关文章

HDU 2222 Keywords Search AC自动机入门题

单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自动机的基础: 1 Trie, 以这个数据结构为基础的,不过增加一个fail指针和构造fail的函数 2 KMP,不是直接运用KMP,而是需要KMP的思想,KMP思想都没有的话,理解这个算法会更加吃力的. 注意本题的单词会有重复出现的,一个单词只能统计一次. 搜索了一下网上的题解,发现好多代码都是一大抄的啊,⊙﹏⊙b汗. 本博客的乃是原创代码,代码风格也是差不多固定的,转载请注明出处:http://blog.c

hdoj 2222 Keywords Search 【AC自动机 入门题】

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 44687    Accepted Submission(s): 14103 Problem Description In the modern time, Search engine came into the life of everybody li

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 2222 Keywords Search(ac自动机入门题)

1 /************************************************************ 2 题目: Keywords Search(hdu 2222) 3 链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 4 算法: ac自动机 5 算法思想: 多个字符串匹配,也就是相当于多个kmp 6 ***********************************************************

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

UVALive-4670 AC自动机入门题 求出现次数最多的子串

/** 链接:http://vjudge.net/problem/UVALive-4670 详见lrj训练指南P216 */ #include<bits/stdc++.h> using namespace std; #define P pair<int,int> #define ms(x,y) memset(x,y,sizeof x) #define LL long long const int maxn = 22; const int mod = 1e9+7; const int

hdu 2222 Keywords Search(AC自动机入门)

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 42138    Accepted Submission(s): 13289 Problem Description In the modern time, Search engine came into the life of everybody like

UVALive 4670 Dominating Patterns --AC自动机第一题

题意:多个模板串,一个文本串,求出那些模板串在文本串中出现次数最多. 解法:AC自动机入门模板题. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <string> #include <vector> #in

HDU 2222 Keywords Search (AC自动机入门 模板)

AC自动机入门 Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.学习AC自动机之前得先有Trie树和KMP模式匹配算法的基础. AC自动机算法分为3步:1.构造一棵tire树  2.构造失败指针  3.进行模式匹配 AC自动机的优化:Trie图 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other