ac自动机

1. 前言

AC自动机:Aho-Corasick automation,是一种多模式匹配算法。
它是在模式树(字典树)Trie和KMP模式匹配算法的基础上进行的。其中,KMP算法是单模式串的字符匹配算法(依次遍历每个元素进行比较的朴素匹配算法+借助于next指针实现)。

2. ac自动机

主要包括三个过程:
(1)建立字典树
(2)构建字典树的每个结点的fail指针
(3)查找过程

比如有模式:“hers”、“his”、“she”、“he”,和匹配的文本"ushers",首先利用上面的4个模式依次:建立字典树、构建每个结点的fail指针、查找文本"ushers"中匹配到的结果。结果如下:[2:3=he, 1:3=she, 2:5=hers],其中文本"ushers"的第2到第3位置匹配到模式"he",其他类似。

(1)建立字典树

在这里插入图片描述
结点表示状态,边表示转态转移的条件, s 0 s_0 s0是根结点,小矩形表示当前结点是某个模式的终结结点,这些模式:“hers”、“his”、“she”、"he"如上图所示。

(2)构建字典树的每个结点的fail指针

fail指针的构建规则是:按照树的层次访问每个结点(借助队列可实现),根结点 s 0 s_0 s0表示树的第0层,这里虚线表示:当前结点的fail的指向。比如,结点 s 1 s_1 s1的fail为 s 0 s_0 s0(第1层的结点的fail都指向根结点)。如下图所示(构建了部分结点的fail指针)
在这里插入图片描述
结点 s i s_i si的构建过程,先是找到它的父结点,然后沿着父结点的fail依次进行,假设到达结点 s i s_i si的转态转移条件是 x x x,这看看该结点的父结点的fail结点加上转移条件 x x x后能否到达一个新的结点 s n e w s_{new} snew,如果可以到达,该结点 s i s_i si的fail则指向新结点 s n e w s_{new} snew;假如该结点的父结点的fail结点加上转移条件 x x x后不能指向新结点,则沿着 s i s_i si.parentNode.failNode的fail的指向继续走下去,当遇到根结点 s 0 s_0 s0时候,加上转移条件 x x x依然还不能指向新结点,则该结点的fail就指向根结点 s 0 s_0 s0

结点 s 5 s_5 s5的fail构建为例有:到达结点 s 5 s_5 s5的转态转移条件是 i i i,结点 s 5 s_5 s5的父结点是结点 s 1 s_1 s1,结点 s 5 s_5 s5的父结点 s 1 s_1 s1的fail结点是 s 0 s_0 s0 s 0 s_0 s0加上转态转移条件 i i i不能指向新结点,而此时 s 0 s_0 s0已经是根结点,所以结点 s 5 s_5 s5的fail指向根结点 s 0 s_0 s0

结点 s 8 s_8 s8的fail构建为例有:到达结点 s 8 s_8 s8的转态转移条件是 h h h,结点 s 8 s_8 s8的父结点是结点 s 7 s_7 s7,结点 s 8 s_8 s8的父结点 s 7 s_7 s7的fail结点是 s 0 s_0 s0 s 0 s_0 s0加上转态转移条件 h h h能指向新结点 s 1 s_1 s1,所以结点 s 8 s_8 s8的fail指向新结点 s 1 s_1 s1

结点 s 9 s_9 s9的fail构建为例有:到达结点 s 9 s_9 s9的转态转移条件是 e e e,结点 s 9 s_9 s9的父结点是结点 s 8 s_8 s8,结点 s 9 s_9 s9的父结点 s 8 s_8 s8的fail结点是 s 1 s_1 s1 s 1 s_1 s1加上转态转移条件 e e e能指向新结点 s 2 s_2 s2,所以结点 s 9 s_9 s9的fail指向新结点 s 2 s_2 s2

(3)查找过程

在这里插入图片描述
以待匹配的文本"ushers"为例:

如上图所示,从根结点 s 0 s_0 s0开始查找,输入状态转移条件 u u u,无法到达新的结点,所以还是在状态 s 0 s_0 s0处接收下一个状态 s s s,此时到达新结点 s 7 s_7 s7,以此类推…

其中,虚线表示要经过fail指针进行查找,即在结点 s 9 s_9 s9处,加上状态 r r r,无法到达新结点,则沿着fail指针查找下去(如果fail指针是根结点,加上状态 r r r依然不能到达新结点,则停止查找),结点 s 9 s_9 s9的fail指向结点 s 2 s_2 s2,结点 s 2 s_2 s2加上状态 r r r能到达结点 s 3 s_3 s3,以此类推…

注意:上图在某些结点处标识模式的结束(在构建字典树时候),当待匹配的文本遇到这些结点的时候,便可以保存当前匹配到的结果,做法如下:以遇到结点 s 9 s_9 s9为例,此时的状态 e e e对于"ushers"来说,index(‘e’)=3,而保存的模式"she"长度为3,由结束index=3计算出开始index=3-len(“she”)+1=1,即在文本"ushers"中,[1:3=she],以此类推…最终的结果有:[2:3=he, 1:3=she, 2:5=hers]

参考
https://github.com/robert-bor/aho-corasick(java版代码)
https://pypi.org/project/pyahocorasick/(python库)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值