AC自动机学习小记

来源:互联网 发布:人工智能算命机器人q 编辑:程序博客网 时间:2024/06/16 01:29

Depend

KMP,Trie.

基本思想

kmp其实是一种特殊的ac自动机.
把n个模式串建成Trie,然后在Trie上跑kmp.(失配退回到fail,也就是kmp所说的next)

fail指针的求法 (ac自动机的关键部分)

x所代表的字符串的定义是: 从root到x这条路径中经过点按序拼接而成的字符串.

fail[x]所代表的字符串是x所代表的字符串的 [Triex]但不一定是x的祖先!,比方说she与he,当是x的祖先的时候就退化成kmp中的next了)。

同样的,KMP中next也是一种特殊的fail指针.

采用与KMP类似的递推求解的方法,
沿着父节点的fail指针走,直到有一个点能匹配上,那么当前节点的fail指到那个节点的匹配儿子去. 若不存在,指到root去让他重新匹配。

由fail[x]所代表的字符串是x所代表的字符串的最长公共后缀可知,跳转的新位置的深度一定小于跳之前的节点。所以我们可以利用 bfs在 Trie上面进行 fail指针的求解。

匹配

一旦失配,则走到fail节点。
匹配成功:当前点是某个模式串的最后一个节点,也就是不一定是Trie的叶子节点!

实现

第一层节点的fail应该为根节点。
求fail的时候,为了更简洁(不写特判),可以让1作为根节点,然后fail[1]=0。这样第一层节点求fail的时候就会自动指到根节点去了。

时间复杂度分析

和KMP类似,fail指针最多往前点数次,因此构造fail复杂度是O(|T|),T是模式串。然而实际上Trie有许多点多串共用,所以复杂度更低,要视题目分析.

匹配基本同上,匹配指针最多往前|S|步,因此复杂度为O(|S|),线性.

还要考虑上字符集的问题,因为Trie遍历有不同方法,空间优秀或时间优秀等等…

AC自动机上进行DP的姿势

通常可以 以生成新串,与主串比较附加代价来理解这个东西。
比方说: 给一个主串和若干个新串,求主串改多少个字符后不存在任意一个子串等于新串。
可设状态f[x][y],现在生成到第x个位置,新生成的这个串如果在自动机上进行匹配的话,应在第y个位置。

不难发现,在自动机上dp的好处是能快速处理模式串带来的贡献(随fail指针下传)

为了降低dp的复杂度,我们应该先求出失配之后到达的点。
(只匹配的不求 是因为反正每个位置都只会走一次,复杂度仍然是线性的。而这个dp他状态不讲道理,每个位置都要求len次失配)。

http://blog.csdn.net/dyx404514/article/details/13776025

1 0
原创粉丝点击