AC自动机(Automaton)
小小总结
- 千万记住insert完以后要build!!!老是忘掉QAQ
- insert函数就只是trie数的插入函数,可在结尾根据条件打一些标记
- build函数(构建fail树),主要利用BFS
- match函数中跑fail树其实就是反复跑后缀
- fail树上倒过来建树以后可以进行很多高端操作,比如阿狸的打字机(也许还能树剖一下QAQ)
- match函数中跑fail树过程可以转化为打标记,而避免重复跑一个相同的后缀,常见优化(见下面的二次加强版板子题)
- 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)相关推荐
- 浅谈Aho-Corasick automaton(AC自动机)
Aho-Corasick automaton是什么? 要学会AC自动机,我们必须知道什么是Trie,也就是字典树.Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统 ...
- Aho-Corasick automaton,ac自动机实现
文章目录 写在前面 算法概述 trie树的构建 trie树的节点结构 插入P串到trie树中 fail指针的创建 搜索过程 测试程序 写在前面 原作者的视频讲解链接:[算法]轻松掌握ac自动机_哔哩哔 ...
- AC自动机——Aho-Corasick Automaton
这是一个英文版的讲的比较好的AC自动机资料. http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf 如果不爱看英文,可以看我整理的大致的 ...
- CDOJ1633 Video Game Combos [AC自动机+dp]
题目地址:http://acm.uestc.edu.cn/problem.php?pid=1633 AC自动机+BFS AC自动机,参见:http://www.cnblogs.com/luna-lov ...
- AC自动机——多个kmp匹配
(并不能自动AC) 介绍: Aho-Corasick automaton,最经典的处理多个模式串的匹配问题. 是kmp和字典树的结合. 精髓与灵魂: ①利用trie处理多个模式串 ②引入fail指针. ...
- 【学习笔记+习题集】字符相关(输入输出流,字典树,AC自动机,后缀自动机)(4598字)(更新至2022.12.28)
目录 板块零:输入输出流 情况一:读取字符串和读取行混用的时候 情况二:关于识别空行 第一题:hdoj2072 情况三:用char数组接受getline函数的输入流 情况四:关于汉字 补充练习: 第一 ...
- 字符串处理【AC自动机】 - 原理 AC自动机详解
字符串处理[AC自动机] - 原理 AC自动机详解 AC自动机(Aho-Corasick automaton)在1975年产生于贝尔实验室,是著名的多模匹配算法. 学习AC自动机,要有KMP和Trie ...
- ac自动机 匹配最长前缀_AC自动机算法
AC自动机简介: 首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包 ...
- Python实现多模匹配——AC自动机
Python实现多模匹配--AC自动机 目标:学习AC自动机,多模匹配. 要求:尽可能用纯Python实现,提升代码的扩展性. 一.什么是AC自动机? AC自动机,Aho-Corasick autom ...
- 算法讲解:ac自动机及简单衍生
AC自动机简介: 首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段 ...
最新文章
- Docker不再是唯一的选择
- linux 卸载模块命令,Linux中module模块的编译、加载、卸载
- python简单代码画图-Python科学画图代码分享
- 查看手机截图的坐标信息
- Codeforces Round #281 (Div. 2) C. Vasya and Basketball 二分
- 三十五、深入Python的引用计数
- python apriori_python apriori算法代码怎么实现
- 你们公司还没使用HTTP3?赶紧来补一补,学习一下如何在Nginx上配置HTTP3。
- HDU-4255 A Famous Grid BFS
- Scrapy开发指南
- webstrom命名改名 命令
- redis(版本redis-5.0.2)的安装步骤
- Linux设备驱动之字符设备(二)
- 自考-计算机程序设计-1-概论
- 音视频编解码基础知识
- Linux服务器CPU性能模式
- element-plus 中loading 自定义图片
- i3cpu驱动xp_Intel英特尔 Core i3/Core i5/Core i7系列CPU显示驱动 14.46.9.5394版 For WinXP-32...
- blender2.8 使用RetopoFlow拓扑手臂护腕 (灵活使用Contours)
- 2021.07.28
热门文章
- Goonie企业竞争情报系统评为选中国优秀网络应用软件奖
- 代购类网站商品高清晰大图片(1000x1000)的采集解决方案 - hackercai - 博客园
- 采用ATSC标准、欧洲DVB-T和日本ISDB-T标准的国家
- 在微型计算机中 集成在微处理,在微型计算机中,微处理器的主要功能是进行什么...
- mybatisplus的逻辑删除
- python用函数求一个数的所有因数_python编程从零基础到项目实践第六章学习---函数 一个完整的求因数函数的完善步骤...
- 一张图看懂零维到十维空间
- ps水彩效果教程-庞姿姿
- 磁珠 符号_超实用理解磁珠
- 52个数据可视化图表鉴赏