0%

AC 自动机

前置知识

KMPtrie

引入

往简单了说,AC自动机其实就是在字典树上搞KMP思想。它能够快速实现在一个文本串中匹配多个模式串。

思路

我们都知道,KMP算法中有一个 nxt 数组,用来处理匹配失败后状态的转移。AC自动机同样有一个这东西,叫做“失配指针”。

但是由于AC自动机匹配多个串,它跳转的不是前缀函数,最长的相同前后缀云云,而是所有状态中和当前状态的后缀相同的最长后缀,这就是说,它可能跳到一个不同的模式串上,只要这个模式串能匹配更多的后缀。

求失配指针

其实它的过程和KMP十分类似:

  • 如果新出现的字符在这里能够继续匹配,或者不能继续匹配但是回到了状态 0,那么这里就是它失配指针对应的位置。
  • 否则当前状态同样没能匹配,沿着当前状态的失配指针继续向前寻找。

ihehisshehers 生成的字典树为例:

<p id="info"></p>
<img id="img" src="/blog/images/ac-auto/1.png" style="" onclick="getNextImg()">
<input type="button" value="<" onclick="getProImg()"/>
<input type="button" value=">" onclick="getNextImg()"/>

绿色的边是失配指针指向的状态;蓝色的边是当前的失配指针;红色的边是求失配指针的过程。

字典图

但是我们可以对上面的思路加以改进。

仔细想一想,对于多个模式串的情况,其实不需要拘泥于仅仅一种失配的情况,而是对于这个节点接下来所遇到的所有可能字符,包括能匹配的和不能匹配的,进行预处理。

这样,我们就能够构造出一个字典图。字典图不仅包含了原来字典树的边,还增加了不同匹配情况所要跳转的位置,所以每个状态都能连出26(对于只有小写字母)条边。

<p id="info2"></p>
<img id="img2" src="/blog/images/ac-auto/1.png" style="" onclick="getNextImg2()">
<input type="button" value="<" onclick="getProImg2()"/>
<input type="button" value=">" onclick="getNextImg2()"/>

(这里将每个点连出的边分开展示,方便观察。* 符号指所有未指定连边的字符。)