NLP笔记:ac自动机实现

1. ac自动机简介

ac自动机算法全称Aho–Corasick算法,它是一种经典的高效字符串匹配算法,他所针对的核心问题为:

如何从一个长字符串中抽取出所有位于目标字典中的词汇。

放到实际问题当中,一个典型的例子就是:

在一串长文本当中,考察其中是否又出现敏感词并对其进行抽取。

一种非常暴力的做法就是对关键词词表中的每个词进行查找,但是这在词表非常大的情况下就会直接炸裂掉,因为他的时间复杂度将会是 O ( l × n × m ) O(l \times n \times m) O(l×n×m)这个量级,其中, l l l为字符串长度, n n n为关键词词表中的词汇数目, m m m为词表中最长的单词长度。

更好地方式是采用trie树,这样可以直接将时间复杂度降至 O ( l × m ) O(l \times m) O(l×m)

有关trie树的原理和实现可以参考我的另一篇文章:Python笔记:Trie树结构简介,里面大致讲了一下trie树的原理,并给了一些leetcode上面的例题说明。

事实上,trie树基本上也就是ac自动机的核心原理了,不过ac自动机的原理更进了一步,他在trie树的基础上引入了失配指针,从而进一步提升了匹配的效率,将时间复杂度降至 O ( l ) O(l) O(l)量级。

更为具体的原理我们在下一个小节中尝试进行说明。

2. ac自动机原理

如前所述,ac自动机核心原理包括两点:

  1. trie树;
  2. 失配指针;

其中,trie树没什么好多说的,可以参考之前的博客:Python笔记:Trie树结构简介,这里就不再赘述了。

重点想说一下失配指针,它的核心功能类似于KMP字符串匹配算法,即当匹配失败时,直接跳转到下一个最长匹配子串。例如,假设一个子串为abcdefk,然后关键词词典中同时有abcdefgcdefk,那么,当匹配到k时,abcdefkabcdefg匹配失败,正常的情况应该是退回到b重新进行匹配,但是,使用了失配指针之后跳转到cdef路径下考察下一个字符串是否是k

不过有关这部分内容的具体实现,我倒是没有想到什么很好的办法,但是下面参考链接中的第一篇文章给了一种基于bfs的算法实现,有兴趣的读者可以参考一下。

btw,参考链接中的第一篇文章是公司里面一个大佬写的,原理上个人觉得讲的真心不错,有兴趣的读者可以细读一下。

3. ac自动机实现

最后,我们来看一下ac自动机在实际使用中的使用方法。

这里,我们主要介绍一下基于pyahocorasick库的ac自动机实现方法。

其安装方式也十分简单,只需要简单地使用下述命令pip安装一下就行了。

pip install pyahocorasick

1. ac自动机的构建

要使用ac自动机进行字符串匹配,我们首先要根据关键词词典构建一个ac自动机。

给出示例代码如下:

keywords = ["abc", "abed", "bcdf", "bcde", "aabe"]

import ahocorasick

# 创建并往 AC 树添加内容
ac = ahocorasick.Automaton()
for w in keywords:
    ac.add_word(w, w)
ac.make_automaton()

2. ac自动机的调用

构建了上述ac自动机之后,我们即可使用iter函数进行string中的关键词匹配。

给出调用代码如下:

s = "abedefaabcdf"
for idx, w in ac.iter(s):
    print("{} :: s[{}:{}]".format(w, idx, idx+len(w)))
# abed :: s[3:7]
# abc :: s[9:12]
# bcdf :: s[11:15]

4. 参考链接

  1. https://mp.weixin.qq.com/s/MtzTpwGZeCroqoGrcokRTg
  2. https://pypi.org/project/pyahocorasick/
  3. https://zh.wikipedia.org/wiki/AC%E8%87%AA%E5%8A%A8%E6%9C%BA%E7%AE%97%E6%B3%95
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值