AC自动机
AC自动机
-
AC自动机:就是在Trie树上进行类似KMP一样的匹配
-
Fail指针:怎么理解Fail指针呢?其实fail指针的含义是我现在走到当前这个节点,如果失配了,那么我应该到Fail指针指向的位置进行匹配。Fail指针指向的是什么东西呢?
盗一张图:) 感谢原作者
虚线表示Fail指针
比如说我当前找ACG,找到G失配了,那么我应该继续往哪走呢?我应该去当前串的最长后缀的串所在的位置。
通俗来说,我现在找ACG,G不是我们要的节点,那么我们显然不需要回到起点重新找一遍,因为我们至少已经找到了C,所以我们应该走到C所在的节点。也就是说,我们最次也找到了ACG除去G的某一个后缀串,所以应该到这个后缀串的位置去继续找。
当然,这个后缀串越长越好。因为比如FXCKYOU的一个后缀是CKYOU,这个后缀可能还有一个后缀YOU。所以当我们发现FXCKYOU的时候,我们肯定已经发现了CKYOU和YOU,所以每次只走到当前串的最长后缀,然后不断循环这个过程,肯定就能找到所有出现在这个串里的串。
同理KMP的失配指针实际上也是这么回事。 -
Trie图:原始的AC自动机里有两种边 next 和 fail . next是存在下一个节点时我们怎么走,fail是不存在下一个节点时我们怎么走。所以我们发现一个问题,对于一个节点的某个后继字母来说,要么存在下一步要么不存在下一步,所以有next的没有fail,有fail的没有next,所以fail和next可以直接合并成一个数组。这就是Trie图了。
对于Trie图来说,每个节点有SIGMA条出边,SIGMA是字符集大小。每条出边代表当前匹配到这个点的时候,如果下一个字母是c,那么我们就沿着当前节点的第c条出边走一步。
Trie图和AC自动机实际上是一个状态转移图。我当前走到某个节点,如果这个节点是单词节点,就代表着我们发现了一些单词。Trie图是一张图,所以我们可以在图上DP,这样就好理解了。状态多数就是走到某个节点时怎么怎么样。
上面那个图实际上就是字符集={A,T,G,C}的一个Trie图。