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:

// Memory   Time
// 1347K     0MS
// by : Snarl_jsb
// 2014-09-30-11.01
#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;

const int N = 10010;
char str[N];
struct node
{
    node *next[128];     //  每个结点都对应128个字母的指针
    node *fail;     //      失配指针
    int count;      //
    int num;
    node()      //  构造函数初始化
    {
        for(int i = 0; i < 128; i++)
            next[i] = NULL;
        count = 0;
        fail = NULL;
        num=0;
    }
}*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] - 31; //  转化为相对数字来存
        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 < 128; 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 total=0;
int Query(node *root,int num)       //  匹配 + 统计
{
    int i = 0, cnt = 0, index;
    node *p = root;
    int idx=0;
    int ans[100];

    while(str[i])
    {
        index = str[i] - 31;
        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 != -1)  //统计--如果匹配成功,那么count>1,表示该结点代表的单词数量;否则表示该结点没有单词
        {
            if(temp->count>0)
            {
                cnt ++; //统计该单词出现的次数
                ans[++idx]=temp->num;
            }
//            temp->count = -1;   //标记为-1,表示该单词已经加入了cnt中,下次就不用重复统计
            temp = temp->fail;//判断整条链上的匹配情况
        }
        i++;
    }
    if(idx==0)
        return 0;
    printf("web %d: ",num);
    sort(ans+1,ans+1+idx);
    total++;
    for(int i=1;i<idx;++i)
    {
        printf("%d ",ans[i]);
    }
    printf("%d\n",ans[idx]);
    return cnt;
}

int main()
{
    int n;
    cin>>n;
    head=tail=0;
    root=new node();
    for(int i=1;i<=n;++i)
    {
        scanf("%s",str);
        Insert(str, i);
    }
    build_ac_automation(root);      //  建树
    int m;
    cin>>m;
    total=0;
    for(int i=1;i<=m;++i)
    {
        scanf("%s",str);
        Query(root,i);
    }
    printf("total: %d\n",total);
    return 0;
}

  

时间: 2024-10-11 00:15:36

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

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_js

【暖*墟】 #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个模式串,

AC自动机——多模式串匹配的算法思想

标准KMP算法用于单一模式串的匹配,即在母串中寻求一个模式串的匹配,但是现在又存在这样的一个问题,如果同时给出多个模式串,要求找到这一系列模式串在母串存在的匹配个数,我们应该如何处理呢? 基于KMP算法,我们能够想到的一个朴素算法就是,枚举这多个模式串,然后进行多次KMP算法,这个过程中完成计数,假设这里有n个模式串,那么整个算法的复杂度大约是O(n*m),m是母串的长度,这里的时间复杂度是粗略估计,没有计算辅助数组的时间(KMP中的next数组),但是这种复杂度还是太高,没有做到KMP算法中“

AC自动机 - 多模式串匹配问题的基本运用 + 模板题 --- HDU 2222

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

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

4.【ac自动机】模式串匹配

ANSI编码的中英文16叉模式串匹配自动机 1.构造模式串树 void insert(char* s, in* trie) { long u = 1, len = strlen(s);//每来一个模式串 for (long i = 0; i < len * 2; i++) { if (i % 2 == 0) { uint8_t vv = (uint8_t)s[i / 2]; uint8_t v = vv >> 4; if (!trie[u].son[v]) trie[u].son[v]

[hdu 2896] 病毒侵袭 [ac自动机][病毒特征码匹配]

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

数据结构14——AC自动机

一.相关介绍 知识要求 字典树Trie KMP算法 AC自动机 多模式串的字符匹配算法(KMP是单模式串的字符匹配算法) 单模式串问题&多模式串问题 单模就是给你一个模式串,问你这个模式串是否在主串中出现过,这个问题可以用kmp算法高效完成: 多模就是给你多个模式串,问你有多少个模式串在这个主串中出现过. 若我们暴力地用每一个模式串对主串做kmp,这样虽然理论上可行,但是时间复杂度非常之高.而AC自动机算法就能高效地处理这种多模式串问题. 二.算法实现 [打基础] 失配指针fail 每个节点都有