AC自动机:

ac自动机其实是吧 kmp 扩展为了 数的形式:

区别:

1.kmp:判断原串中,求一个单词是否出现过,以及出现次数,出现位置的查找--       O(n)

2.求解 每一个单词出现次数 --O(n)

实在AC自动机就是在一个 trie上求一个next数组:

定义: ne[i], 所有以i  结尾的最长非平凡后缀 相等的前缀 尾端点位置,也就是当前单词的后缀可以匹配的最长前缀,也即 与当前匹配的字串最大后缀相同的前缀位置,来进行下一次匹配

AC自动机其实是类比kmp在一维数组求next 的操作,在树上实现,树的每层遍历依赖bfs实现

他本质上是对trie 的kmp

为什么要求next数组:

当我们在字典树上进行一次匹配,匹配成功 or失败的时候,我们的当前位置定位到比较下面的节点,按照暴力思想我们回退到根节点重新匹配,效率过低

so我们需要像kmp一样求next数组,当发生匹配失败or匹配完成的时候,我们利用nexr数组回退到一个最合适的位置--next数组也叫失配指针 -fail

含义为:如果一个点ii的FailFail指针指向jj。那么rootroot到jj的字符串是rootroot到ii的字符串的一个后缀。(参考大佬博客:AC自动机 - hyfhaha 的博客 - 洛谷博客 (luogu.com.cn)

比如:

上图, 当 i 不匹配时我们需要回退到一个与当前单词 i (4)的最大后缀相等的位置,

很明显在图中 是 7,这个位置也就是我们的 j了

i:4 j:7 root到i的字符串是“ABC”

root到j的字符串是“BC”

“BC”是“ABC”的一个后缀 所以i的Fail指针指向j

同时我们发现,“C”也是“ABC”的一个后缀。

所以Fail指针指的jj的深度要尽量大。

在定义一下Fail吧:((最长的(当前字符串的后缀))在TrieTrie上可以查找到)的末尾编号。

trie:字典树,又称前缀树,是用于快速处理字符串的问题,能做到快速查找到一些字符串上的信息。

另外,Trie树在实现高效的同时,会损耗更多的空间,所以Trie是一种以空间换时间的算法。

那么基本思想已知,我们如何实现呢?

1.)首先我们需要一颗 trie ,下面是传入多个 str的 建数代码:

 2).然后我们要模仿 kmp 进行 求next数组:

注意我们这里从kmp过度后的含义:

1.因为是建立在 trie上的我们 需要一层层遍历,so,我们利用bfs遍历每一层=

2.有kmp中 j的含义知道 j=next[i-1];(next[i]=j; i++; ->j=next[i-1];)

so我们次数的 j 利用的就是上一个(层)--t ->j=ne[t];

3.kmp中利用 s[i] == p[j+1] 判断下一位是否匹配,我们此处需要改为 tr[j][i] 这条路径是否存在

if存在 就可以继续往下走了 j=tr[j][i];

3).匹配操作:

1.根据kmp的经验我们知道 匹配操作使和求next数组相似的,不同的是我们这里的j从0 开始表示从根节点开始匹配(查到单词当然要从第一个字母开始了)

 2.剩下的依然模仿求next数组,if tr[j][t] 这条路不存在,那么久回退到合适的位置

3.问题需要求 目标单词出现的次数之和,我们统计完之后记得 cnt =0,以防再次遇到的时候重复统计

哎呀!! 这样想想是不是觉得还缺什么呢?明明是线性时间复杂度的ac自动机却有个while来拖后腿,我们有没有办法设法将其优化呢?

有的,我们可以借助trie的性质:只要每次找到不存在的路径时,把它的next更新为他父节点的next即可。不存在只能回退了嘛。

举个例子:

    // 假定在循环第i层时,前i-1层都求对了
    // 在第i层没找到字母i,那么去第i-1层父结点t的next指针的位置就是它最终应该跳到的位置

这样一层一层更新,每次i都参照的是已经更新并且正确的i-1,那么是不是可以在线性复杂度下求出所有的next了呢

求next数组的优化:

 匹配时候的优化:

这优化的效果是当不匹配的时候我们平常需要的while多次 回退,变成只需要 一步回退即可回退到最佳位置。。 

练习题:

0.trie的基础题(先理解trie的思想再学ac自动机就会比好懂):P2580 于是他错误的点名开始了 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

当然这个模板题也可以用map来水过去,但是我们最好还是使用trie的写法去了解我们的trie

1.模板题:1282. 搜索关键词 - AcWing题库

2.1285. 单词 - AcWing题库

(用cnt来记录前缀出现次数,然后bfs是拓补序的倒叙,倒着输出即可)

3.P3796 【模板】AC 自动机(加强版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

4.P5357 【模板】AC 自动机(二次加强版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值