ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AC自动机【学习笔记】

2020-05-16 15:55:02  阅读:246  来源: 互联网

标签:AC 后缀 匹配 Trie 笔记 trie fail 自动机 指针


 

概述

$AC$自动机是以$Trie$为结构基础,$kmp$为思想基础建立的,主要用于多模式串匹配。

在$AC$自动机上,所有的模式串构成一棵$Trie$树,而且利用$kmp$的思想,在$Trie$上构造失配指针。

$Trie$上的结点表示的是某个模式串的前缀,相当于一种状态,而$Trie$上的边就相当于是状态的转移。

$fail$指针

先把所有的模式串放到$Trie$,举例如下:

 

 

 

 假如说现在要匹配的文本串是$ABCD$,我们去树上匹配,会经过$2,3,4$号节点匹配到模式串$ABC$,然后就不能继续匹配。


 如果接下来重新从根结点开始,复杂度会很高,我们可以借用$kmp$的思想,跳到$7$去,$7$就是$4$的失配指针。

 More  officially,$fail$指针指向 / 模式串的前缀中 / 匹配 / 当前状态的最长后缀。(断句要断好)
 也就是说,$i$的失配指针$j$,满足$root->j$是$root->i$的一个后缀,而且是所有满足$root->i=root->j_x$中最大的那一个$j_x$。
 $9$号点也满足条件,但是那里不是最长后缀,所以我们不跳到那里去。
 
下面是$fail$的求法:
设$Trie$上当前的节点是$u$,$u$的父亲是$p$,$trie[p][c]=u$。
假设深度小于$u$的所有结点的$fail$指针都已经求过。

1.$trie[fail[p]][c]$存在,那么$fail[u]=trie[fail[p]][c]$。$p$的最长后缀的位置在$fail[p]$,在$fail[p]$的位置再加一个字符$c$就一定$u$的最长后缀的位置,因为只在一个确定的串后面加上一个字符而已。
2.如果$trie[fail[p]][c]$不存在,那么就要一直跳$fail$指针(反复横跳),找$trie[fail[fail[p]]][c]$,直到它存在,然后重复1.
3.如果真的不存在,那么把$fail$指向根。

具体可以用$bfs$实现(有假设深度小于$u$的所有结点的$fail$指针都已经求过) ,不过实现和刚才的思考过程是反的。
$tr[u][c]$可以理解为字典树上的一条边,也可以理解为一种状态转移,表示$u$加上一个字符$c$达到的状态。

 

 

 


代码实际上修改了$Trie$的结构,但是使得匹配转移更加完善。它将 fail 指针跳转的路径做了压缩(就像并查集的路径压缩),使得本来需要跳很多次$ail$针变成跳一次。

匹配函数

$fail$是最难的部分,$fail$理解之后求答案就水到渠成了吧。

 

 

时间复杂度

 

 

 

【参考:OIwiki】

标签:AC,后缀,匹配,Trie,笔记,trie,fail,自动机,指针
来源: https://www.cnblogs.com/lyttt/p/12900804.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有