算法学习:AC自动机
【定义】
【自动机】 由 状态集 ,初始状态集 ,终止状态集 ,字母集 ,对应关系五个元素组成的结构
可以简单的将状态集理解为结点,初始状态集理解为初始点,终止状态集理解为终点
字母集理解为一个状态能够拥有的出边的最大个数,而在自动机中,特殊的是,一个结点的所有出边必须都要存在
例如在AC自动机中,每个节点都必须要有26个字母的出边所指向的节点
对应关系,可以理解为连通的边,例:节点 u 的 ’a‘ 的出边能够到达节点 v ,这就是一组对应关系
注:自动机的概念不用知道也可以学自动机,但是个人感觉理解了自动机的含义,更容易去明白他的本质
而且后面学其他自动机也更容易理解
【模式串】 一个比较短的串,需要找 文本串上有多少个他
【文本串】 一个比较长的串,需要在 他上面有多少个模式串
【前置知识】
【trie树(字典树)】从根节点插入一个字符串,依次插入
【KMP】单文本 logn 复杂度内查找模式串出现次数
【强烈建议看最后的扩展】
【解决问题】
多个模式串匹配文本串
给定一个较长串为文本串,给定多个模式串,询问这两者的关系
(也有可能不只有一个文本串)
一般为出现次数什么的
AC自动机本身保存这个字符串的所有子串的相关信息
即这个子串作为模式串出现的次数,这个子串的后缀之中能够包含多少模式串
【算法思想】
这个自动机的优点和KMP类似,所以有的博客中也会说,这是一个树上KMP。
KMP的优点在于有next数组作为指针失配时的指针,使字符串匹配可以不需要再次查找已经查找的串
而AC自动机也有他的“next数组”,f a i l 。
AC自动机中的 f a i l 指针表示的是,当当前匹配的模式串失效后,已经匹配的一半模式串的拥有最长后缀的模式串的结尾的位置
对于一个AC自动机,我们需要先把所有的模式串都插入一颗 trie 树
int trie[MAXN][26]; //s是需要插入的模式串 void insert(string s) {int u = 0;//从根节点开始检索for (int i = 0; i < s.size(); i++){int x = s[i] - 'a';if (!trie[u][x])//如果没有这个节点//需要新开拓一个节点,保存这个新的分支 {trie[u][x] = ++cnt;}u = trie[u][x];}val[u]++;//说明这个节点是一个模式串的结尾return; }
然后根据我们对 f a i l 的定义去寻找f a i l 指针
void get_fail() {queue<int> q;for (int i = 0; i < 26; i++) if (trie[0][i]) fail[trie[0][i]] = 0, q.push(trie[0][i]);//让所有的根节点连接的节点的fail指针指向根节点//并且加入队列while (!q.empty()){int u = q.front(); q.pop();for (int i = 0; i < 26; i++)//循环查找每个字母 if (trie[u][i])//如果存在这个节点// {//他的 fail 就是 他父节点的 fail 的这个字母的位置//因为等于是在后缀上新加了一个字母 fail[trie[u][i]] = trie[fail[u]][i];q.push(trie[u][i]);}elsetrie[u][i] = trie[fail[u]][i];//如果没有//向上递归一层,方便之后的查找 }return; }
这里应该有张图说明一下,但是我懒得画
【模板题】
【题目大意】给n个模式串和1个文本串,问有多少个模式串在文本串中出现过
【解决方法】在trie树上跑文本串
int query(string s) {int u = 0, ans = 0;//从根节点开始依次查找for (int i = 0; i < s.size(); i++){u = trie[u][s[i] - 'a'];//走到自己这个位置字符所在的节点for (int t = u; t && ~val[t]; t = fail[t])//从这个节点开始向上跳fail指针//查找有没有符合要求的字符串,如果是则这个字符串就会被记录ans += val[t], val[t] = -1;//-1是为了防止被重复计算 }return ans; }
#include<cstdio> #include<iostream> #include<string> #include<queue> using namespace std; const int MAXN = 1000010; int fail[MAXN],cnt; int trie[MAXN][26]; int val[MAXN]; void insert(string s) {int u = 0;for (int i = 0; i < s.size(); i++){int x = s[i] - 'a';if (!trie[u][x]){trie[u][x] = ++cnt;}u = trie[u][x];}val[u]++;return; } void get_fail() {queue<int> q;for (int i = 0; i < 26; i++) if (trie[0][i]) fail[trie[0][i]] = 0, q.push(trie[0][i]);while (!q.empty()){int u = q.front(); q.pop();for (int i = 0; i < 26; i++)if (trie[u][i]){fail[trie[u][i]] = trie[fail[u]][i];q.push(trie[u][i]);}elsetrie[u][i] = trie[fail[u]][i];}return; } int query(string s) {int u = 0, ans = 0;for (int i = 0; i < s.size(); i++){u = trie[u][s[i] - 'a'];for (int t = u; t && ~val[t]; t = fail[t])ans += val[t], val[t] = -1;}return ans; } int main() {int T;cin >> T;while (T--){string s;cin >> s;insert(s);}get_fail();string s;cin >> s;printf("%d", query(s));return 0; }
View Code
【扩展】
这一步扩展其实才是AC自动机的精髓所在,也是比赛中比较常用的方法
就像是网络流不可能直接给图找最大流,而是通过建图的方式考察对算法的理解
AC自动机也有同样的情况
那就是通过抽离 fail 指针,建 fail 树,并且对其进行一系列操作完成任务
这不就是AC自动机抽离fail指针建可持久化线段树么
讲解在另外一道题里面
【NOI 2011】 阿狸的打字机
转载于:https://www.cnblogs.com/rentu/p/11297951.html
算法学习:AC自动机相关推荐
- 算法导论—AC自动机
华电北风吹 日期:2016-05-03 AC自动机是比较高效的多模式匹配算法.类似于KMP在模式串上的状态转移算法,AC自动机通过在trie树上建立状态转移,使得对匹配串遍历一遍就可以找到所有的模式串 ...
- KMP算法、AC自动机算法的原理介绍以及Python实现
KMP算法 要弄懂AC自动机算法,首先弄清楚KMP算法. 这篇文章讲的很好: http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E ...
- 提高篇 第二部分 字符串算法 第4章 AC自动机
https://blog.csdn.net/wangyh1008/article/details/81428056 [模板]AC自动机(加强版) 洛谷3796 AC自动机_A_loud_name-CS ...
- 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)
图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...
- ac自动机 匹配最长前缀_AC自动机算法
AC自动机简介: 首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包 ...
- AC自动机算法及模板
AC自动机算法及模板 2016-05-08 18:58 226人阅读 评论(0) 收藏 举报 分类: AC自动机(1) 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 关于 ...
- AC自动机 算法详解(图解)及模板
要学AC自动机需要自备两个前置技能:KMP和trie树(其实个人感觉不会kmp也行,失配指针的概念并不难) 其中,KMP是用于一对一的字符串匹配,而trie虽然能用于多模式匹配,但是每次匹配失败都需要 ...
- AC自动机模板(【洛谷3808】)
题面 题目背景 这是一道简单的AC自动机模版题. 用于检测正确性以及算法常数. 为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交. 题目描述 给定n个模式串和1个文本串,求有多少个模式串 ...
- 字符串处理【AC自动机】 - 原理 AC自动机详解
字符串处理[AC自动机] - 原理 AC自动机详解 AC自动机(Aho-Corasick automaton)在1975年产生于贝尔实验室,是著名的多模匹配算法. 学习AC自动机,要有KMP和Trie ...
- Python实现多模匹配——AC自动机
Python实现多模匹配--AC自动机 目标:学习AC自动机,多模匹配. 要求:尽可能用纯Python实现,提升代码的扩展性. 一.什么是AC自动机? AC自动机,Aho-Corasick autom ...
最新文章
- DevOps:怎么实现源代码注释和系统文档的自动化更新?
- 35岁不是程序员的坎儿,看不清楚这件事才是!
- golang map 判断key是否存在
- display属性_前端基础:Grid 布局教程,重新复习grid布局的容器和项目属性
- 2019年最值得关注的五大微服务发展趋势
- 算法笔记_100:蓝桥杯练习 算法提高 三个整数的排序(Java)
- 持有1000枚以上比特币的巨鲸地址数量有所下降
- php mail带附件,Pear Mail 发送邮件带附件_PHP教程
- mouseclick
- 搭建内网文件共享服务器,如何搭建共享服务器实现办公室文件共享?
- 英语发音规则---/ŋ/与/ŋg/的读音区别
- 计量经济学及Stata应用 陈强 第九章模型设定与数据问题习题9.3
- windows 7 远程桌面连接图文教程
- 全栈云服务是个什么东东?!
- win10 休眠设置无效_win10电脑休眠后无法唤醒的解决办法
- 嵌入式GEC6818利用多线程实现视频播放器
- 历经5年,一次业余网页游戏项目惨痛的失败经历
- php处理并发不如java_今天听人说 php 运算能力不比 java
- 关系数据库的查询处理
- 计算机二级成绩划分标准,计算机二级 成绩 等级是如何划分的
热门文章
- kafka模拟生产-消费者以及自定义分区
- 4.5/4.6 磁盘格式化 4.7/4.8 磁盘挂载 4.9 手动增加swap空间
- c++——结构与指针 类与指针
- 《信息可视化:交互设计(原书第2版)》——第2章基本概念
- vs转eclipse之工具快速上手篇
- 关于UIView的userInteractionEnabled属性
- iOS APP提交上架最新流程(转)
- 3D图形图像处理软件HOOPS介绍及下载
- 在linux下配置oracle的远程访问
- AWS推出深度学习容器,简化AI程序开发