小小总结

  1. 千万记住insert完以后要build!!!老是忘掉QAQ
  2. insert函数就只是trie数的插入函数,可在结尾根据条件打一些标记
  3. build函数(构建fail树),主要利用BFS
  4. match函数中跑fail树其实就是反复跑后缀
  5. fail树上倒过来建树以后可以进行很多高端操作,比如阿狸的打字机(也许还能树剖一下QAQ)
  6. match函数中跑fail树过程可以转化为打标记,而避免重复跑一个相同的后缀,常见优化(见下面的二次加强版板子题)
  7. AC自动机常与数位DP结合,毕竟数字和字符串长得差不多

洛谷-P3808 简单板子题

//#pragma comment(linker, "/STACK:102400000,102400000")
#include "bits/stdc++.h"
#define pb push_back
#define ls l,m,now<<1
#define rs m+1,r,now<<1|1
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}const int maxn = 1e5+10;
const int mod = 1e9+7;
const double eps = 1e-9;int trie[maxn][26], cnt;
int e[maxn];
int fail[maxn];void insert(char *s) {int p=0;for(int i=0; s[i]; ++i) {int k=s[i]-'a';if(!trie[p][k]) trie[p][k]=++cnt;p=trie[p][k];}e[p]++;
}void build() {queue<int> q;memset(fail,0,sizeof(fail));for(int i=0; i<26; ++i) if(trie[0][i]) q.push(trie[0][i]);while(!q.empty()) {int k=q.front(); q.pop();for(int i=0; i<26; ++i) {if(trie[k][i]) {fail[trie[k][i]]=trie[fail[k]][i];q.push(trie[k][i]);}else trie[k][i]=trie[fail[k]][i];}}
}
int match(char *t) {int p=0, res=0;for(int i=0; t[i]; ++i) {p=trie[p][t[i]-'a'];for(int j=p; j&&~e[j]; j=fail[j]) res+=e[j], e[j]=-1;}return res;
}char t[maxn];int main() {//ios::sync_with_stdio(false);int n=read();for(int i=0; i<n; ++i) {scanf("%s", t);insert(t);}build();scanf("%s", t);printf("%d\n", match(t));
}

洛谷-P3796 加强板子题

//#pragma comment(linker, "/STACK:102400000,102400000")
#include "bits/stdc++.h"
#define pb push_back
#define ls l,m,now<<1
#define rs m+1,r,now<<1|1
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0', c=getchar();return x;
}const int maxn = 1e6+10;
const int mod = 1e9+7;
const double eps = 1e-9;struct Result{int num, id;bool operator < (const Result &rhs) const{if(num==rhs.num) return id<rhs.id;return num>rhs.num;}
}res[151];string l[151];int trie[maxn][26], cnt;
int e[maxn];
int fail[maxn];void init() {memset(trie,0,sizeof(trie));memset(e,0,sizeof(e));memset(fail,0,sizeof(fail));cnt=0;
}void insert(int id) {int len=l[id].size();int p=0;for(int i=0; i<len; ++i) {int k=l[id][i]-'a';if(!trie[p][k]) trie[p][k]=++cnt;p=trie[p][k];}e[p]=id;
}void build() {queue<int> q;memset(fail,0,sizeof(fail));for(int i=0; i<26; ++i) if(trie[0][i]) q.push(trie[0][i]);while(!q.empty()) {int k=q.front(); q.pop();for(int i=0; i<26; ++i) {if(trie[k][i]) {fail[trie[k][i]]=trie[fail[k]][i];q.push(trie[k][i]);}else trie[k][i]=trie[fail[k]][i];}}
}
void match(const string &t) {int len=t.size();int p=0;for(int i=0; i<len; ++i) {p=trie[p][t[i]-'a'];for(int j=p; j; j=fail[j]) res[e[j]].num++;}
}int main() {//ios::sync_with_stdio(false);int n;while(cin>>n, n) {init();for(int i=1; i<=n; ++i) {cin>>l[i];insert(i);res[i].num=0;res[i].id=i;}build();cin>>l[0];match(l[0]);sort(res+1,res+1+n);printf("%d\n", res[1].num);for(int i=1; i<=n; ++i) {if(res[i].num==res[1].num) cout<<l[res[i].id]<<endl;else break;}}
}

洛谷-P5357 二次加强板子题

fail树(DAG)上拓扑排序加速跑fail的过程

//#pragma comment(linker, "/STACK:102400000,102400000")
#include "bits/stdc++.h"
#define pb push_back
#define ls l,m,now<<1
#define rs m+1,r,now<<1|1
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}const int maxn = 2e6+10;
const int mod = 1e9+7;
const double eps = 1e-9;char s[maxn];
int trie[maxn*5][26], num[maxn*5], in[maxn*5], fail[maxn*5], cnt;
int pos[maxn];void insert(int id) {int len=strlen(s), p=0;for(int i=0; i<len; ++i) {int k=s[i]-'a';if(!trie[p][k]) trie[p][k]=++cnt;p=trie[p][k];}pos[id]=p;
}void build() {queue<int> q;for(int i=0; i<26; ++i) if(trie[0][i]) q.push(trie[0][i]);while(q.size()) {int now=q.front(); q.pop();for(int i=0; i<26; ++i) {if(trie[now][i]) {fail[trie[now][i]]=trie[fail[now]][i];in[trie[fail[now]][i]]++;q.push(trie[now][i]);}else trie[now][i]=trie[fail[now]][i];}}
}void match() {int len=strlen(s), p=0;for(int i=0; i<len; ++i) {p=trie[p][s[i]-'a'];num[p]++;}
}void solve() {queue<int> q;for(int i=0; i<=cnt; ++i) if(!in[i]) q.push(i);while(q.size()) {int now=q.front(); q.pop();num[fail[now]]+=num[now];if(--in[fail[now]]==0) q.push(fail[now]);}
}int main() {//ios::sync_with_stdio(false);int n=read();for(int i=1; i<=n; ++i) { scanf("%s", s); insert(i); }build();scanf("%s", s);match();solve();for(int i=1; i<=n; ++i) printf("%d\n", num[pos[i]]);
}

AC自动机(Automaton)相关推荐

  1. 浅谈Aho-Corasick automaton(AC自动机)

    Aho-Corasick automaton是什么? 要学会AC自动机,我们必须知道什么是Trie,也就是字典树.Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统 ...

  2. Aho-Corasick automaton,ac自动机实现

    文章目录 写在前面 算法概述 trie树的构建 trie树的节点结构 插入P串到trie树中 fail指针的创建 搜索过程 测试程序 写在前面 原作者的视频讲解链接:[算法]轻松掌握ac自动机_哔哩哔 ...

  3. AC自动机——Aho-Corasick Automaton

    这是一个英文版的讲的比较好的AC自动机资料. http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf 如果不爱看英文,可以看我整理的大致的 ...

  4. CDOJ1633 Video Game Combos [AC自动机+dp]

    题目地址:http://acm.uestc.edu.cn/problem.php?pid=1633 AC自动机+BFS AC自动机,参见:http://www.cnblogs.com/luna-lov ...

  5. AC自动机——多个kmp匹配

    (并不能自动AC) 介绍: Aho-Corasick automaton,最经典的处理多个模式串的匹配问题. 是kmp和字典树的结合. 精髓与灵魂: ①利用trie处理多个模式串 ②引入fail指针. ...

  6. 【学习笔记+习题集】字符相关(输入输出流,字典树,AC自动机,后缀自动机)(4598字)(更新至2022.12.28)

    目录 板块零:输入输出流 情况一:读取字符串和读取行混用的时候 情况二:关于识别空行 第一题:hdoj2072 情况三:用char数组接受getline函数的输入流 情况四:关于汉字 补充练习: 第一 ...

  7. 字符串处理【AC自动机】 - 原理 AC自动机详解

    字符串处理[AC自动机] - 原理 AC自动机详解 AC自动机(Aho-Corasick automaton)在1975年产生于贝尔实验室,是著名的多模匹配算法. 学习AC自动机,要有KMP和Trie ...

  8. ac自动机 匹配最长前缀_AC自动机算法

    AC自动机简介: 首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包 ...

  9. Python实现多模匹配——AC自动机

    Python实现多模匹配--AC自动机 目标:学习AC自动机,多模匹配. 要求:尽可能用纯Python实现,提升代码的扩展性. 一.什么是AC自动机? AC自动机,Aho-Corasick autom ...

  10. 算法讲解:ac自动机及简单衍生

    AC自动机简介:  首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段 ...

最新文章

  1. Docker不再是唯一的选择
  2. linux 卸载模块命令,Linux中module模块的编译、加载、卸载
  3. python简单代码画图-Python科学画图代码分享
  4. 查看手机截图的坐标信息
  5. Codeforces Round #281 (Div. 2) C. Vasya and Basketball 二分
  6. 三十五、深入Python的引用计数
  7. python apriori_python apriori算法代码怎么实现
  8. 你们公司还没使用HTTP3?赶紧来补一补,学习一下如何在Nginx上配置HTTP3。
  9. HDU-4255 A Famous Grid BFS
  10. Scrapy开发指南
  11. webstrom命名改名 命令
  12. redis(版本redis-5.0.2)的安装步骤
  13. Linux设备驱动之字符设备(二)
  14. 自考-计算机程序设计-1-概论
  15. 音视频编解码基础知识
  16. Linux服务器CPU性能模式
  17. element-plus 中loading 自定义图片
  18. i3cpu驱动xp_Intel英特尔 Core i3/Core i5/Core i7系列CPU显示驱动 14.46.9.5394版 For WinXP-32...
  19. blender2.8 使用RetopoFlow拓扑手臂护腕 (灵活使用Contours)
  20. 2021.07.28

热门文章

  1. Goonie企业竞争情报系统评为选中国优秀网络应用软件奖
  2. 代购类网站商品高清晰大图片(1000x1000)的采集解决方案 - hackercai - 博客园
  3. 采用ATSC标准、欧洲DVB-T和日本ISDB-T标准的国家
  4. 在微型计算机中 集成在微处理,在微型计算机中,微处理器的主要功能是进行什么...
  5. mybatisplus的逻辑删除
  6. python用函数求一个数的所有因数_python编程从零基础到项目实践第六章学习---函数 一个完整的求因数函数的完善步骤...
  7. 一张图看懂零维到十维空间
  8. ps水彩效果教程-庞姿姿
  9. 磁珠 符号_超实用理解磁珠
  10. 52个数据可视化图表鉴赏