AC自动机(板子总结)

【数据结构】自动机全家桶(AC、回文、后缀自动机) AC自动机、回文自动机、后缀自动机 阅读详情

板子来源

题解 P3808 【【模板】AC自动机(简单版)】 - 洛谷专栏

心得

刷了洛谷之后发现,自己之前暴力跳fail可以被卡,改成trie图优化的板子了

板子整理

P3808【模板】AC自动机(简单版)

统计一下文本串里,模式串一共出现过几个,其中相同的只算一次,保证无任意两个模式串相同

#include<bits/stdc++.h>
#define N 500010
using namespace std;
namespace AC{
    int nex[N][26],num[N],fail[N],c;
    void init(){
        c=0;
        memset(nex[c],0,sizeof nex[c]);
        fail[c]=num[c]=0;
    }
    void ins(char *s,int n){
        int rt=0;
        for(int i=0;i<n;i++){
            int v=s[i]-'a';
            if(!nex[rt][v]){
                nex[rt][v]=++c;
                memset(nex[c],0,sizeof nex[c]);
                fail[c]=num[c]=0;
            }
            rt=nex[rt][v];
        }
        num[rt]++;
    }
    void build(){
        queue<int>q;
        for(int i=0;i<26;i++){
            if(nex[0][i]){
                fail[nex[0][i]]=0,q.push(nex[0][i]);
            }
        }
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++){
                if(nex[u][i])fail[nex[u][i]]=nex[fail[u]][i],q.push(nex[u][i]);
                else nex[u][i]=nex[fail[u]][i];
            }
        }
    }
    int query(char *s,int n){
        int rt=0,ans=0;
        for(int i=0;i<n;i++){
            rt=nex[rt][s[i]-'a'];
            for(int j=rt;j && ~num[j];j=fail[j]){//防止重搜
                ans+=num[j],num[j]=-1;
            }
        }
        return ans;
    }
};
using namespace AC;
int n;
char p[1000005];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",p);
        ins(p,strlen(p));
    }
    build();
    scanf("%s",p);
    printf("%d\n",query(p,strlen(p)));
    return 0;
}
P3796 【模板】AC自动机(加强版)

文本串中,输出最大的模式串出现次数,及对应的所有模式串,保证无任意两个模式串相同

多模式匹配,统计每个串的出现次数,经典题目;

暴力跳fail的复杂度据说不大正确,所以像SAM那样,

打差分标记,即沿途经过的点标记num值加1,实际它是一个应该对其所有fail都+1的差分标记,

再按fail树由叶子向根做前缀和,实际上这个顺序是插入时的逆序,用队列存下来即可

#include<bits/stdc++.h>
#define N 70*150+5
using namespace std;
namespace AC{
    int nex[N][26],num[N],id[N],fail[N],q[N],h,t,c;
    void init(){
        c=0;
        memset(nex[c],0,sizeof nex[c]);
        fail[c]=num[c]=id[c]=0;
    }
    void ins(char *s,int n,int x){
        int rt=0;
        for(int i=0;i<n;i++){
            int v=s[i]-'a';
            if(!nex[rt][v]){
                nex[rt][v]=++c;
                memset(nex[c],0,sizeof nex[c]);
                fail[c]=num[c]=id[c]=0;
            }
            rt=nex[rt][v];
        }
        id[rt]=x;
    }
    void build(){
        h=1;t=0;
        for(int i=0;i<26;i++){
            if(nex[0][i]){
                fail[nex[0][i]]=0,q[++t]=nex[0][i];
            }
        }
        while(h<=t){
            int u=q[h++];
            for(int i=0;i<26;i++){
                if(nex[u][i])fail[nex[u][i]]=nex[fail[u]][i],q[++t]=nex[u][i];
                else nex[u][i]=nex[fail[u]][i];
            }
        }
    }
    void query(char *s,int n){
        int rt=0;
        for(int i=0;i<n;i++){
            rt=nex[rt][s[i]-'a'];
            num[rt]++;
        }
    }
};
using namespace AC;
int n;
char txt[155][75],p[1000005];
int main(){
    while(~scanf("%d",&n) && n){
        init();
        for(int i=1;i<=n;i++){
            scanf("%s",txt[i]);
            ins(txt[i],strlen(txt[i]),i);
        }
        build();
        scanf("%s",p);
        query(p,strlen(p));
        for(int i=t;i>=1;--i){
            int v=q[i];
            num[fail[v]]+=num[v];
        }
        int mx=0;
        for(int i=1;i<=c;++i){
            if(id[i])mx=max(mx,num[i]);
        }
        printf("%d\n",mx);
        for(int i=1;i<=c;++i){
            if(id[i] && mx==num[i]){
                printf("%s\n",txt[id[i]]);
            }
        }
    }
    return 0;
}
P5357【模板】AC自动机(二次加强版)

统计每个模式串在文本串中出现的次数,可能存在两个或多个模式串完全相同

完全相同的,在trie树上开散列存下标即可,这里用的vector,剩下的与上一题相同

#include<bits/stdc++.h>
#define N 200005
using namespace std;
namespace AC{
    int nex[N][26],num[N],fail[N],q[N],h,t,c;
    vector<int>id[N];
    void init(){
        c=0;
        memset(nex[c],0,sizeof nex[c]);
        fail[c]=num[c]=0;
        id[c].clear();
    }
    void ins(char *s,int n,int x){
        int rt=0;
        for(int i=0;i<n;i++){
            int v=s[i]-'a';
            if(!nex[rt][v]){
                nex[rt][v]=++c;
                memset(nex[c],0,sizeof nex[c]);
                fail[c]=num[c]=0;
                id[c].clear();
            }
            rt=nex[rt][v];
        }
        id[rt].push_back(x);
    }
    void build(){
        h=1;t=0;
        for(int i=0;i<26;i++){
            if(nex[0][i]){
                fail[nex[0][i]]=0,q[++t]=nex[0][i];
            }
        }
        while(h<=t){
            int u=q[h++];
            for(int i=0;i<26;i++){
                if(nex[u][i])fail[nex[u][i]]=nex[fail[u]][i],q[++t]=nex[u][i];
                else nex[u][i]=nex[fail[u]][i];
            }
        }
    }
    void query(char *s,int n){
        int rt=0;
        for(int i=0;i<n;i++){
            rt=nex[rt][s[i]-'a'];
            num[rt]++;
        }
    }
};
using namespace AC;
int n,ans[N];
char p[2000005];
int main(){
    scanf("%d",&n);
    init();
    for(int i=1;i<=n;i++){
        scanf("%s",p);
        ins(p,strlen(p),i);
    }
    build();
    scanf("%s",p);
    query(p,strlen(p));
    for(int i=t;i>=1;--i){
        int v=q[i];
        num[fail[v]]+=num[v];
    }
    for(int i=1;i<=c;++i){
        for(int j=0;j<id[i].size();++j){
            int x=id[i][j];
            ans[x]=num[i];
        }
    }
    for(int i=1;i<=n;++i){
        printf("%d\n",ans[i]);
    }
    return 0;
}

AC自动机板子 RT: 题面 待封装: #include<bits/stdc++.h> #include<bits/extc++.h> using namespace std; #define _rep(i, a, b) for (int i = (a); i <= (b); ++i) #define _rev(i, a, b) for (int i = (a); i >= (... 阅读详情

相关推荐

保姆级教程:在K230开发板上为张大头步进电机实现位置、速度、回零全功能控制

本文提供了一份详细的K230开发板与张大头步进电机的控制教程,涵盖硬件连接、协议解析、模块化代码实现及实战案例。通过位置、速度和回零功能的全面讲解,帮助开发者快速掌握步进电机的高级控制技术,适用于自动化、机器人等应用场景。

weixin_42629671的博客 710

AC自动机-详解AC自动机以及模板

AC自动机-详解AC自动机以及模板AC自动机算法简介AC自动机算法大致流程AC自动机详细图解AC自动机模板题与模板题目内容代码详解完整代码 AC自动机算法简介 首先简要介绍一下AC自动机,英文名:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模板匹配算法之一。一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章,让你找出有多少个单词在文章里出现过。 要搞懂AC自动机,先要有字典树Trie和KMP模式匹配算法的基础知识。其中,KMP是用于一对一的字符串匹

qq_43381135的博客 6856

以TMS320F28069为例,如何使用CCS建立DSP工程文件

以TMS320F28069为例,本文主要介绍了使用CCS建立DSP工程的流程

Honglong 2555

AC自动机(简单模板)

与上一题不一样的只有一小部分,这题中,每个字符串可重复记录,所以就不能加上那个线性优化,还需要记录每个字符串出现的次数即可。AC自动机,就相当于是在字典树上用kmp。next数组回退的位置为最大匹配字符串在字典树上的节点位置。在获取字典树上的next数组的时候用的是BFS每次相当与处理的一层。下图中红线为,可以回退的位置,没有红线的节点回退的位置都是虚拟原点。

qq_64468032的博客 745

【第48例】BLM模型之市场洞察-五看工具篇(一)

BLM市场洞察

产品线负责人 2109

增益调度控制 —— 理论、案例与交互式 GUI 实现

本文详细介绍了增益调度控制的基本原理、数学模型及公式推导,探讨了该方法在适应非线性系统和大范围工作条件下的优势与局限。通过航空飞行控制、发动机推力控制以及化工过程控制三个典型案例,我们展示了如何利用调度变量动态调整控制增益,从而使得控制系统在各个工作点均能达到优良性能。为帮助工程师和研究者更直观地理解并验证增益调度控制的实际效果,本文提供了一套基于 Python 与 PyQt6 的交互式 GUI 控制系统代码。用户不仅可以实时查看仿真数据,还能通过在线调节参数直观体验调度控制的优势。

闲人编程的博客 1480

【字符串】AC自动机 - 模板

AC自动机可以理解成字典树上的kmp,kmp是在一个长串里查找一个单词的出现次数,而AC自动机是在一个长串里一次性查找多个单词的出现次数。

Texcavator的博客 1398

ROS从入门到精通0-4:VSCode 搭建 ROS 工程环境

为了提高开发效率,可以先安装集成开发工具和使用方便的工具,本教程用VSCode搭建ROS工程环境

FRIGIDWINTER的博客 1万+

AC自动机(模板)

对于每组数据,第一行一个整数 n,接下去 n 行表示 n 个单词,最后一行输入一个字符串,表示文章。给定 n 个长度不超过 5050 的由小写英文字母组成的单词,以及一篇长为 m的文章。对于每组数据,输出一个占一行的整数,表示有多少个单词在文章中出现。第一行包含整数 T,表示共有 T组测试数据。请问,其中有多少个单词在文章中出现了。

q619718的博客 251

RK3568项目(四)--uboot启动流程之启动模式选择

本章接着上面,接着来分析uboot启动流程,设计vendor、按键、驱动模式的选择等

文艺小少年的博客 584

YOLOv8【第十一章:视频追踪与流处理篇·第6节】BoT-SORT 改进:结合相机运动补偿(CMC)提升追踪稳定性!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。

**My Coding Family** 718

trie树+AC自动机板子

trie树(hihocoder1014) #include #include #include typedef long long ll; typedef struct node; char str[12]; struct node{ int s; node*nxt[26]; }*root; ll ans=0;//root inline node* build(){ node*a=(nod

博客迁移http://www.cnblogs.com/xzz_233/ 370

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【板子】AC 自动机

多模式串匹配问题:给定一堆模式串,一个长文本,一次性找出文本里所有出现过的模式串。暴力:每个模式串单独 KMP,总复杂度爆炸。AC 自动机 =,线性处理。

ysa051030的博客 324

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

hdu2222(AC自动机板子题)

终于搞懂了AC自动机 #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<iostream> #include<string.h> using namespace std; const int maxn = 5000...

qq_41780519的博客 262

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

AC自动机(Trie 板子)&后缀数组模板(解决原串与子串问题)

大自然的帮运工 使用板子注意事项: 注意: 1.串是否全是小写字母 2.根节点为1 3.节点数不超过maxn 4.多组数据注意 清空 5.复杂度嘛。。。。。建树o(n*len) 前置知识:Trie树 需求: 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。 输入n个模式串, 一个原串 输出结果: 原串中含有模式串的个数。 in: 6 abcd cd cd cdac aab abcdac out: 5 #include<bits/stdc++.h> #define maxn

weixin_45819197的博客 411

hdu2222-AC自动机板子

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意 t组数据,每组数据给出n个子串,再给出一个主串,问主串中有多少个子串。每个串只计算一次,同时输入的串不保证不重复。 AC自动机的模板题,构建好AC自动机之后,直接一位一位的查询是否是结束点。模板是学kuangbin大佬的,比较简洁易懂。 123456789...

测试 344

AC自动机 板子

if (AC[now].vis[s[i] - 'a'] == 0)//Trie树没有这个子节点。t = AC[t].fail)//循环求解。++i)//构造Trie树。int AC_Query(string s)//AC自动机匹配。

weixin_75192140的博客 144

HDU 2222 ac自动机板子

题目链接: https://vjudge.net/problem/HDU-2222 题意: 给n个模式串,一个文本串,问有多少个 模式串在文本串中 出现了。 代码: #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=5e5+5; int trie[maxn][...

lt的博客 177

ac自动机板子

procedure insert; var now,i:longint; dd:char; begin now:=1;len:=length(s); for i:=1 to len do begin dd:=s[i]; if t[now].son[dd]=0 then begin inc(tt);t[no...

weixin_30399055的博客 74

HDU 2222 (AC自动机 板子题)

题目链接:点击这里AC自动机板子题#include <bits/stdc++.h> using namespace std; #define maxn 511111 #define maxm 1111111struct trie { int next[maxn][26], fail[maxn], end[maxn]; int root, cnt; int new_node (

morejarphone~ 447
上一篇: 原根(知识学习+板子总结+例题+应用)
下一篇: hdu3065 病毒侵袭持续中(AC自动机模板题)
小衣同学
博客等级 码龄9年 1444粉丝 995原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值