(模板)AC自动机模板

1. 给出模式串和文本串,文本串长度小于1e6,模式串长度之和小于1e6,求文本串中有多少模式串出现。

题目链接:https://www.luogu.org/problem/P3808

AC code:

/*
    luoguP3808 (AC自动机模板题)
    求文本串中有多少模式串出现
*/
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;

const int maxn=1e6+5;
struct Tree{          //Trie树
    int fail,vis[30],key; //key用来记录有几个单词以这个节点结尾
}AC[maxn];
int n,cnt;
char s[maxn];
//在Trie树中插入结点
void build(char *s){
    int len=strlen(s),u=0;
    for(int i=0;i<len;++i){
        int t=s[i]-‘a‘;
        if(!AC[u].vis[t])
            AC[u].vis[t]=++cnt;
        u=AC[u].vis[t];
    }
    AC[u].key+=1;
}
//构建fail指针
void get_fail(){
    queue<int> que;
    for(int i=0;i<26;++i){  //提前处理第二层
        if(AC[0].vis[i]){
            AC[AC[0].vis[i]].fail=0;  //指向根节点
            que.push(AC[0].vis[i]);
        }
    }
    while(!que.empty()){    //bfs求所有子结点
        int u=que.front();
        que.pop();
        for(int i=0;i<26;++i){
            if(AC[u].vis[i]){
                AC[AC[u].vis[i]].fail=AC[AC[u].fail].vis[i];
                que.push(AC[u].vis[i]);
            }
            else{
                AC[u].vis[i]=AC[AC[u].fail].vis[i];
            }
        }
    }
}
//AC自动机匹配
int query(char *s){
    int len=strlen(s),u=0,ans=0;
    for(int i=0;i<len;++i){
        int t=s[i]-‘a‘;
        u=AC[u].vis[t];
        for(int j=u;j&&AC[j].key!=-1;j=AC[j].fail){ //循环求解
            ans+=AC[j].key;
            AC[j].key=-1;
        }
    }
    return ans;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%s",s);
        build(s);
    }
    AC[0].fail=0;   //结束标志
    get_fail();     //求失配指针
    scanf("%s",s);
    printf("%d\n",query(s));
    return 0;
}

原文地址:https://www.cnblogs.com/FrankChen831X/p/11875749.html

时间: 2024-08-01 16:00:57

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

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

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

hdu2222(ac自动机模板)

先推荐两篇写的很好的ac自动机blog: http://blog.csdn.net/creatorx/article/details/71100840 http://blog.csdn.net/niushuai666/article/details/7002823 正题 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意: 给出 n 个模式串以及一个 主串, 问有多少个模式串在主串中出现过 思路: ac自动机模板题 代码: 1 #inc

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

多模匹配 题目大意:给定很多个字串A,B,C,D,E....,然后再给你目标串str字串,看目标串中出现多少个给定的字串. 经典AC自动机模板题,不多说. 1 #include <iostream> 2 #include <algorithm> 3 #include <functional> 4 #include <string.h> 5 #define MAX 26 6 7 using namespace std; 8 9 struct node 10 {

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

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

[hdu2222] [AC自动机模板] Keywords Search [AC自动机]

AC自动机模板,注意!ch,Fail,lab数组的大小不是n而是节点个数,需要认真计算! 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <ctime> 7 #include <cstdlib> 8 #include <queue>

HDU 2222(AC自动机模板题)

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

HDU 2222 Keyword Search AC自动机模板

#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #include <ctime> #include <io

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

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

HDU3695(AC自动机模板题)

题意:给你n个字符串,再给你一个大的字符串A,问你着n个字符串在正的A和反的A里出现多少个? 其实就是AC自动机模板题啊( ╯□╰ ) 正着query一次再反着query一次就好了 /* gyt Live up to every day */ #include<cstdio> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<st