自然语言处理hanlp------8AC自动机

本文涉及的产品
NLP自然语言处理_高级版,每接口累计50万次
NLP自然语言处理_基础版,每接口每天50万次
NLP 自学习平台,3个模型定制额度 1个月
简介: 自然语言处理hanlp------8AC自动机

前言

DAT每次转移的时间复杂度都是常数,全切分长度为n的文本时,时间复杂度是0(n2 ^22


例子:

假设词典收录了所以的阿拉伯数字,那么对文本“123”进行扫描,发生了6次的状态转移

1、12、123;2、23;3

推广一下:“123···n”扫描就发生了n+(n-1)+(n-2)+···+1=2(n+1)n
=0(n2 ^22次状态转移


但是,我们学习自然语言处理就为了更快,更牛逼!

AC自动机就是一种可以一次扫描查询出所有出现的单词的复杂度为0(n)的多模式匹配算法。

简单说一下AC自动机的AC,就是这俩人,贝尔实验室的Aho和Corasick。


提示:以下是本篇文章正文内容,下面案例可供参考


一、从字典树到AC自动机

前面说了例子,就是为了让一次扫描查询所有出现过的单词。我们过渡到了AC自动机。字典树是前缀树,AC自动机是在前缀树的基础上,为前缀树上的每个节点建立一颗后缀树。节省大量的查询时间。

AC自动机goto表fail表output表组成。


1. goto表

goto表也称作success表,如下举例理解:


使用ushers为母文本,模式串集合为{he,she,his,hers}

此时的goto表为

20210201142235241.png

它的构建和前缀树一致,唯一不同的地方是:根节点不光可以按照h和s转移,还接受其他任意字符,转移终点都是自己。这样形成了一个圈,圈的目的在于扫描时若遇到非h且非s的字符,状态机一直保持初始状态。


2.output表

这个很简单,写出对应的状态编号的输出值的表就行了

20210201182135617.png


将其与goto表结合如下

2021020118241738.png

output 表中的元素有两种,一种是从初始状态到当前状态的路径本身对应的模式串(比如2号状态),另一种是路径的后缀所对应的模式串(比如5号状态)。于是它的构造也分为两步,第一步与字典树类似,就是记录完整路径对应的模式串。第二步则是找出所有路径后缀及其模式串,这一步可以与fail表的构造同步进行。


3.fail表

fail表中保存了失配时的fail指针,fail指针就是当前位置失配以后能够跳转继续进行匹配的字符位置,达到匹配过程中不需要回溯的效果。构建过程使用了BFS(宽度优先搜索)算法。


晗佬的解释是:fail表保存的是状态间一对一的关系,存储状态转移失败后应当回到的最佳状态。最佳状态指的是能记住已匹配上的字符串的最长后缀的那个状态


仍然从实例来理解fail表如何创建


(1)初始状态的goto表是满的,永远不会失败,因此没有fail指针。与初始状态直接相连的所有状态,其fail指针都指向初始状态,如图2-11中的虚线所示。

20210201183928206.png

(2)从初始状态开始进行广度优先遍历(BFS),若当前状态S接受子符c直达的状态为T,则沿着S的fail指针回溯,直到找到第一个前驱状态F,使得 F.goto( c ) != null。将T的fail指针设为F.goto( c ),也即:

F = S.fail
while F.goto( c ) == null
    F = F.fail
T.fail = F.goto( c )


(3)由于F路径是T路径的后缀,也就是说T一定包含F,因而T的 output也应包含F的output。于是更新:

T.output += F.output


完善后得出:(反复多对照图和上述流程理解就可)

20210201191351440.png


从后往前看,便是后缀树,举例一个如下:

20210201191902761.png

字典树状态转移可能失败,失败时扫描起点往右挪―下,重新扫描。而在AC自动机中,按goto表转移失败时就按fail表转移永远不会失败,因此只需扫描一遍文本。


二、代码实现(看看即可)

自动机状态部分代码

image.png


fail表建立部分代码:

image.png


演示上述经典案例ushers

20210201193852823.png


三、速度测评

仍然是直接上晗佬的测评结果

image.png

可以看出,已经比BinTrie快了一点了,但比前面所需的DAT双数组字典树,还是逊色了一些,这里,我们就可以考虑,如果将双数组与AC自动机结合会怎么样呢??也就是下节的内容了。


总结

晗佬的书循序渐进,亲情推荐大家买来阅读,一步一步,相信我们都可以真正的去入门自然语言处理!



相关文章
|
自然语言处理 算法 Java
自然语言处理hanlp------6-1字典树的实现
自然语言处理hanlp------6-1字典树的实现
自然语言处理hanlp------6-1字典树的实现
|
自然语言处理 算法 Java
自然语言处理hanlp------6-2字典树的实现
自然语言处理hanlp------6-2字典树的实现
自然语言处理hanlp------6-2字典树的实现
|
自然语言处理 Java Python
自然语言处理hanlp------4词典
自然语言处理hanlp------4词典
自然语言处理hanlp------4词典
|
自然语言处理 算法 Java
自然语言处理hanlp------5切分算法
自然语言处理hanlp------5切分算法
自然语言处理hanlp------5切分算法
|
自然语言处理 算法 Java
自然语言处理hanlp------7-1双数组字典树
自然语言处理hanlp------7-1双数组字典树
自然语言处理hanlp------7-1双数组字典树
|
自然语言处理 Python
自然语言处理hanlp------1安装
自然语言处理hanlp------1安装
自然语言处理hanlp------1安装
|
自然语言处理 算法
【自然语言处理】N-最短路径法进行中文分词
【自然语言处理】N-最短路径法进行中文分词
194 0
【自然语言处理】N-最短路径法进行中文分词
|
存储 自然语言处理
自然语言处理hanlp------9基于双数组字典树的AC自动机
自然语言处理hanlp------9基于双数组字典树的AC自动机
自然语言处理hanlp------9基于双数组字典树的AC自动机
|
存储 自然语言处理 算法
自然语言处理hanlp------7-2双数组字典树(*初学者可选择性学习)
自然语言处理hanlp------7-2双数组字典树(*初学者可选择性学习)
自然语言处理hanlp------7-2双数组字典树(*初学者可选择性学习)
|
自然语言处理 Python
自然语言处理hanlp------2初体验
自然语言处理hanlp------2初体验
自然语言处理hanlp------2初体验