秉着能偷懒就偷懒的精神,关于AC自动机本来不想看的,但是HanLp的源码中用户自定义词典的识别是用的AC自动机实现的。唉~没办法,还是看看吧

AC自动机理论

Aho Corasick自动机,简称AC自动机,要学会AC自动机,我们必须知道什么是Trie,也就是字典树。Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。之前已经写过关于Tire与双数组Tire(Double Array Tire,以下简称DAT)的文章

AC自动机的优点

AC的优点其实包括了所有Tire树的优点,而且更加强大,考虑下面的问题

对一个长字符串S,给定一个模式串T,查看模式串T是否在S中出现过?

这个问题简单的算法就是便利S与T中的字符逐个比较,不一致则移到S的下一个字符。这种算法最坏情况下的时间复杂度是O(len(S) * len(T))

而广为人知的KMP算法就是省去了逐个比较的过程,而是直接按照next数组中的内容来进行查找,复杂度为O(len(S) + len(T))

而AC自动机较之于DAT的优点就是增加一个fail表,而省去在DAT多模式匹配时无所谓的回溯,(不过后来HanLp的作者做了实验,效率不如DAT呢。)

AC自动机的构造

知道了AC的强大,下面来看AC的构造,构造之前,先看一张AC的图,对字典{FG,HE,HERS,HIS,SHE}构造的Tire树就如下图所示:

乍一看这个图很复杂,其实,只是在TIRE的基础上,对每个节点,加上了一个fail指针,如图中的虚线所示

AC自动机的构造

AC建立是构建在TIRE基础上的,DAT的两要素为BASE与CHECK表,而AC的三要素为goto表,fail表与output表

goto: 即分支与儿子节点

fail :某状态匹配失败,回到fail所指状态继续匹配

output表: 状态对应的输出

把大象装冰箱分3步,所以AC构造过程也分3步:

1. 对字典建立TIRE树结构,建立过程中  goto表也随之建好(即指向子节点的指针),output表初步建成,之后还要根据fail指针去扩充output,下图"[]"中的内容即为初步的output表,对应于字典中的下标

2. 步骤1生成的TIRE树,虽然有树形结构,但状态值都为0,下面用TIRE构造DAT,并且对状态State赋值。

  注意,构造过程中,对是一个词的节点,即图中的绿色节点,在构造DAT时,会长生一个子节点,即标识一个词的结尾,类似与上一篇中提到的叶节点结构,到增加的子节点的转移字符取0即可,新增节点的state值即为父节点的base值

3. 遍历带有状态的TIRE,构造fail表与output表。

构造失败指针的原理: 对某个节点,其产生于字母C,沿着此节点的父节点的失败指针走,知道某个节点,他的分支状态中也有字母C,然后把当前节点的失败指针指向那个分支C指向的儿子节点,如果一直啊到root都没有这样的节点,则失败指针指向root即可。原理同KMP算法,不明白可以谷歌之。构造完后的图即如第一张图所示。

下图即构造完成后,各个表中的内容:

至此  AC自动机便构造完成了,接下来就看看怎么用它去分词了。

参考资料

Aho Corasick自动机结合DoubleArrayTrie极速多模式匹配

中文分词系列(二) 基于双数组Tire树的AC自动机的更多相关文章

  1. 中文分词系列(一) 双数组Tire树(DART)详解

    1 双数组Tire树简介 双数组Tire树是Tire树的升级版,Tire取自英文Retrieval中的一部分,即检索树,又称作字典树或者键树.下面简单介绍一下Tire树. 1.1 Tire树 Trie ...

  2. 从Trie树到双数组Trie树

    Trie树 原理 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,能在常数时间O(len)内实现插入和查 ...

  3. 双数组Trie树(DoubleArrayTrie)Java实现

    http://www.hankcs.com/program/java/%E5%8F%8C%E6%95%B0%E7%BB%84trie%E6%A0%91doublearraytriejava%E5%AE ...

  4. Ansj分词双数组Trie树实现与arrays.dic词典格式

    http://www.hankcs.com/nlp/ansj-word-pairs-array-tire-tree-achieved-with-arrays-dic-dictionary-format ...

  5. 中文分词实践(基于R语言)

    背景:分析用户在世界杯期间讨论最多的话题. 思路:把用户关于世界杯的帖子拉下来.然后做中文分词+词频统计,最后将统计结果简单做个标签云.效果例如以下: 兴许:中文分词是中文信息处理的基础.分词之后.事 ...

  6. Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401开发

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  7. [转]双数组TRIE树原理

    原文名称: An Efficient Digital Search Algorithm by Using a Double-Array Structure 作者: JUN-ICHI AOE 译文: 使 ...

  8. 双数组Trie树 (Double-array Trie) 及其应用

    双数组Trie树(Double-array Trie, DAT)是由三个日本人提出的一种Trie树的高效实现 [1],兼顾了查询效率与空间存储.Ansj便是用DAT(虽然作者宣称是三数组Trie树,但 ...

  9. 双数组trie树的基本构造及简单优化

    一 基本构造 Trie树是搜索树的一种,来自英文单词"Retrieval"的简写,可以建立有效的数据检索组织结构,是中文匹配分词算法中词典的一种常见实现.它本质上是一个确定的有限状 ...

随机推荐

  1. Javascript 图片延迟加载之理论基础

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  2. (转)白话经典算法系列之八 MoreWindows白话经典算法之七大排序总结篇

    在我的博客对冒泡排序,直接插入排序,直接选择排序,希尔排序,归并排序,快速排序和堆排序这七种常用的排序方法进行了详细的讲解,并做成了电子书以供大家下载.下载地址为:http://download.cs ...

  3. mysql之select(二)

    union 联合 作用: 把2次或多次查询结果合并起来. 要求:两次查询的列数一致.推荐:查询的每一列,相对应得列类型也一样. 可以来自于多张表.多次sql语句取出的列名可以不一致,此时,以第1个sq ...

  4. VISO下载地址

    http://pan.baidu.com/share/home?uk=4011207371#category/type=0

  5. Winsock IOCP模型(四篇)

    http://blog.csdn.net/visualeleven/article/details/6041893 http://blog.csdn.net/visualeleven/article/ ...

  6. CentOS编译安装Python3

    前话 最近想学一下一门新的高级语言,无意中看到用python仿AIphaGo的github项目,就决定是他了. AIphaGo的Git传送门: https://github.com/Rochester ...

  7. IDL基础

    先列后行 arr=indgen(3,4) SIZE(arr,/dimensions) print ,where(arr gt7) print,arr[where(arr gt 7)] print,wh ...

  8. Linux命令-date

    [root@localhost ~]# date 2016年 09月 07日 星期三 :: CST [root@localhost ~]# date "+%Y" [root@loc ...

  9. JSP的设计模式

    1.JSP模型1(JSP+JavaBean) JSP页面负责处理请求,并将响应发送给客户端.JSP页面文件包括:login.html.loginchk.jsp.welcome.jsp.JavaBean ...

  10. opencv 人脸识别 (二)训练和识别

    上一篇中我们对训练数据做了一些预处理,检测出人脸并保存在\pic\color\x文件夹下(x=1,2,3,...类别号),本文做训练和识别.为了识别,首先将人脸训练数据 转为灰度.对齐.归一化,再放入 ...