AC自动机 - AC自动机 - 多模式串的匹配运用 --- HDU 3065

病毒侵袭持续中

Problem‘s Link:http://acm.hdu.edu.cn/showproblem.php?pid=3065



Mean:

中文题,不解释。

analyse:

AC自动机的运用。这一题需要将模式串都存储下来,还有就是base的取值一定要弄清楚,由于这题的模式串都是大写字母所以我们可以通过剪枝来加速。

Time complexity:o(n)+o(ml) 

Source code:

// Memory   Time
// 1347K     0MS
// by : Snarl_jsb
// 2014-09-30-21.00
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<climits>
#include<cmath>
#define LL long long
using namespace std;

char backup[1002][53];
int res[1002];
const int N = 1010;
char str[2000010];
struct node
{
    node *next[26];     //  每个结点都对应26个字母的指针
    node *fail;     //      失配指针
    int count;      //
    int num;
    node()      //  构造函数初始化
    {
        for(int i = 0; i < 26; i++)
            next[i] = NULL;
        count = 0;
        num=0;
        fail = NULL;
    }
}*q[50*N];
node *root;
int head, tail;

void Insert(char *str,int num) //   插入单词.相当于构建一个Trie树
{
    node *p = root;
    int i = 0, index;
    while(str[i])
    {
        index = str[i] - ‘A‘; //  转化为相对数字来存
        if(p->next[index] == NULL) // 该字母未插入过
            p->next[index] = new node();    //  为该字母申请一个结点
        p = p->next[index];     //   移至下一个
        i++;
    }
    p->count++;     //      记录该结点的单词总共插入的次数
    p->num=num;
}
void build_ac_automation(node *root)        //      bfs建立fail指针
{
    root->fail = NULL;
    q[tail++] = root;
    while(head < tail) {
        node *temp = q[head++];
        node *p = NULL;
        for(int i = 0; i < 26; i++) {
            if(temp->next[i] != NULL) {
                if(temp == root) temp->next[i]->fail = root;
                else {
                    p = temp->fail;
                    while(p != NULL) {
                        if(p->next[i] != NULL) {
                            temp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if(p == NULL) temp->next[i]->fail = root;
                }
                q[tail++] = temp->next[i];
            }
        }
    }
}

int Query(node *root)       //  匹配 + 统计
{
    int i = 0, cnt = 0, index;
    node *p = root;
    while(str[i])
    {
        index = str[i] - ‘A‘;
        if(index<0||index>25)   ///这个地方要特别注意,由于病毒只包含大写字母,所以这儿需要剪枝,不剪枝的话其他地方加判断也可以过
		{
			p=root;
			i++;
			continue;
		}
        while(p->next[index] == NULL && p != root) //前缀是相同的,所以不管哪个指针走到了count不为0的结点上,那么该结点所代表的单词就匹配成功
            p = p->fail;//失配情况下,p指针指向p->fail.(相当于KMP的next数组)
        p = p->next[index];//由于现在所在的位置是父节点,所以需要向下移动一个位置
        if(p == NULL)
            p = root; //如果匹配失败,移动到root,重新开始匹配
        node *temp = p;//
        while(temp != root && temp->count>0)  //统计--如果匹配成功,那么count>1,表示该结点代表的单词数量;否则表示该结点没有单词
        {
//            cnt += temp->count; //统计该单词出现的次数
            res[temp->num]++;   //每次回溯都会加1
//            temp->count = -1;   //!!!!!!!!!!!!!!!!!(如果要重复统计,请讲这句去掉)!!!!!!!!标记为-1,表示该单词已经加入了cnt中
            temp = temp->fail;//判断整条链上的匹配情况
        }
        i++;
    }
    return cnt;
}

int main()
{
    int n,m;
    while(cin>>n)
    {
        head = tail = 0;    //  清零
        root = new node();      //  申请新的root结点
        memset(backup,0,sizeof(backup));
        memset(res,0,sizeof(res));
        for(int i=1;i<=n;++i)
        {
            scanf("%s",str);
            strcpy(backup[i],str);
            Insert(str,i);
        }
        build_ac_automation(root);
        scanf("%s",str);
        Query(root);
        for(int i=1;i<=n;++i)
        {
            if(res[i])
            {
                printf("%s: %d\n",backup[i],res[i]);
            }
        }
    }
    return 0;
}

  

时间: 2024-10-05 12:25:21

AC自动机 - AC自动机 - 多模式串的匹配运用 --- HDU 3065的相关文章

AC自动机 - 多模式串的匹配运用 --- HDU 2896

病毒侵袭 Problem's Link:http://acm.hdu.edu.cn/showproblem.php?pid=2896 Mean: 中文题,不解释. analyse: AC自动机的运用,多模式串匹配.就是有几个细节要注意,在这些细节上卡了半天了. 1)输出的网站编号和最终的病毒网站数不是一样的: 2)next指针要设128,不然会爆栈: 3)同理,char转换为int时,base要设为31: Time complexity:o(n)+o(ml)  Source code: // M

【暖*墟】 #AC自动机# 多模式串的匹配运用

一.构建步骤 1.将所有模式串构建成 Trie 树 2.对 Trie 上所有节点构建前缀指针(类似kmp中的next数组) 3.利用前缀指针对主串进行匹配 AC自动机关键点一:trie字典树的构建过程 字典树的构建过程是这样的,当要插入许多单词的时候,我们要从前往后遍历整个字符串, 当我们发现当前要插入的字符其节点再先前已经建成,我们直接去考虑下一个字符即可, 当我们发现当前要插入的字符没有再其前一个字符所形成的树下没有自己的节点, 我们就要创建一个新节点来表示这个字符,接下往下遍历其他的字符.

【算法】AC自动机/AC算法 - 多模式串快速匹配

AC自动机 Accepted Aho-Corasick 性质 AC自动机/AC算法(Aho-Corasick automaton),是著名的多模式串匹配算法. 前置知识 字典树(重要) KMP算法(了解Next数组的作用) 典例与算法复杂度分析 典型例题是:给定一个主串 S,给定多个模式串 T,问主串 S 中存在多少个给定的模式串 在KMP算法中,一个长度为n的主串一个长度为m的模式串的复杂度为 O(n+m) 而如果直接照搬KMP算法到这种题型下,模式串处理一次就需要匹配一次 如果有t个模式串,

POJ 3167 Cow Patterns(模式串浮动匹配)

题目链接:http://poj.org/problem?id=3167 题意:模式串可以浮动的模式匹配问题给出模式串的相对大小,需要找出模式串匹配次数和位置. 思路:统计比当前数小,和于当前数相等的,然后进行kmp. 比如说模式串:1,4,4,2,3,1 而主串:5,6,2,10,10,7,3,2,9,那么2,10,10,7,3,2就是匹配的 code: 1 #include <cstdio> 2 #include <cstring> 3 #include <vector&g

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出现失配,并开始下一个字符就行了

hdu5384 AC自动机模板题,统计模式串在给定串中出现的个数

http://acm.hdu.edu.cn/showproblem.php?pid=5384 Problem Description Danganronpa is a video game franchise created and developed by Spike Chunsoft, the series' name is compounded from the Japanese words for "bullet" (dangan) and "refutation&q

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

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

hdu2222 AC自动机-给定串中出现了几个模式串

http://acm.hdu.edu.cn/showproblem.php?pid=2222 Problem Description In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a lo