HDU 2222 (AC自动机模板题)

题意:

给一个文本串和多个模式串,求文本串中一共出现多少次模式串

分析:

ac自动机模板,关键是失配函数

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
#define N 250010
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
struct Trie{
    int ch[N][26],val[N],f[N],last[N],num;
    void init(){
        num=1;
        memset(ch,0,sizeof(ch));
        memset(val,0,sizeof(val));
        memset(f,0,sizeof(f));
        memset(last,0,sizeof(last));
    }
    void print(int j){
        if(j){
            printf("%d: %d\n", j, val[j]);
            print(last[j]);
        }
    }
    void build(char *s){
        int u=0,len=strlen(s);
        for(int i=0;i<len;++i)
        {
            int v=s[i]-‘a‘;
            if(!ch[u][v]){
                memset(ch[num],0,sizeof(ch[num]));
                ch[u][v]=num++;
            }
            u=ch[u][v];
        }
        val[u]++;
    }  //失配函数
    void getfail(){
        queue<int>q;
        for(int i=0;i<26;++i)
            if(ch[0][i])
            q.push(ch[0][i]);
        while(!q.empty()){
            int r=q.front();
            q.pop();
            for(int i=0;i<26;++i)
            {
                int u=ch[r][i];
                if(!u)continue;
                q.push(u);
                int v=f[r];
                while(v&&!ch[v][i])v=f[v];
                f[u]=ch[v][i];
                last[u]=val[f[u]]?f[u]:last[f[u]];
            }
        }
    }
    int find(char *T){
        int u=0,len=strlen(T);
        int total=0;
        for(int i=0;i<len;++i){
            int v=T[i]-‘a‘;
            while(u&&ch[u][v]==0)
                u=f[u];
            u=ch[u][v];
            int tmp=u;
            while(tmp&&val[tmp]){
                total+=val[tmp];
                val[tmp]=0;
                tmp=f[tmp];
            }
        }
        return total;
    }
}ac;
int main()
{
    char s[60],T[1000010];
    int t,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        ac.init();
        while(n--){
            scanf("%s",s);
            ac.build(s);
        }
        ac.getfail();
        scanf("%s",T);
        printf("%d\n",ac.find(T));
    }
return 0;
}
时间: 2024-09-29 23:55:32

HDU 2222 (AC自动机模板题)的相关文章

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

<题目链接> 题目大意: 给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词. 解题分析: 这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非常多的时候,耗时会非常多,所以这里用到了AC自动机,这是一种类似于Trie树的数据结构,但是同时,它也用到了KMP算法中 next数组的思想. 下面是AC自动机指针形式的题解: #include <stdio.h> #include <stdlib.h> #include <st

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,所以先备份一下,

HDU 2222 AC自动机(模版题)

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

HDU 2222(AC自动机模板题)

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

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

原题大意:原题链接 先给定T个单词,然后给定一个字符串,查询该字符串中包含多少个给定的单词 解题思路:AC自动机模板题 参考链接:哔哩哔哩算法讲堂 WA版本 注意:因为输入的单词可能有重复,那么Insert()函数中p->id=id;语句中p->id会被覆盖,在Query()函数中会一次性全部被清零,导致不能查询重复单词,以至于结果res错误. #include<queue> #include<cstdio> #include<cstring> using

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

LA 4670 出现次数最多的子串 (AC自动机模板题)

Dominating Patterns Time Limit:3000MS   Memory Limit:Unknown   64bit IO Format:%lld & %llu [Submit]  [Go Back]  [Status] Description The archaeologists are going to decipher a very mysterious ``language". Now, they know many language patterns; ea

NYOJ 1085 数单词 (AC自动机模板题)

数单词 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 为了能够顺利通过英语四六级考试,现在大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中可以通过六级,可是没想到,成绩出来以后,居然没有通过.所以他不得不付出更多的时间来学习英语. 要想通过六级,最基本的要求就是词汇量.为了能够更快的记住一些陌生单词,LYH有时会找一些英语文章来读. 今天早上,LYH又找了一篇文章.读之前,他突然萌生出一个想法:文章中哪些单词出现的次数最多呢? 输入 第一行输入一个