秉着能偷懒就偷懒的精神,关于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 nextElementSibling和nextSibling

    function next(ele) { if (typeof ele.nextElementSibling == 'object') { return ele.nextElementSibling; ...

  2. light oj 1068 - Investigation 数位DP

    思路:典型的数位DP!!! dp[i][j][k]:第i位,对mod取余为j,数字和对mod取余为k. 注意:由于32位数字和小于95,所以当k>=95时,结果肯定为0. 这样数组就可以开小点, ...

  3. SQL Server 基础 之 GROUP BY子句

    GROUP BY 子句用于聚合信息 先看个实例,没有使用 GROUP BY 子句 SELECT SalesOrderID,OrderQty FROM Sales.SalesOrderDetail WH ...

  4. Linux网络编程2——系统函数

    socket信息数据结构 #include <netinet/in.h> struct sockaddr { unsigned short sa_family; /*地址族*/ ]; /* ...

  5. C 和C++ 名称修饰规则

    C名称修饰规则 1.对于使用__cdecl调用约定的函数,在函数名称前加一下划线,不考虑参数和返回值. 2.对于使用__fastcall调用约定的函数,在函数名称前后各加一@符号,后跟参数的长度,不考 ...

  6. php用fsockopen实现post提交数据并获得返回数据

    /** * 函数介绍: 用于post方式提交数据 * 输入参数: 完整url, 数据 * 返回值 : 接口返回值 */ function post_it($url, $data = '', $time ...

  7. android-non-ui-ui-thread-communications-part-5-5

    This is the last post in my series regarding Android thread communications.  Parts 1 through 4 are l ...

  8. grep sed

    grep -q angeltoto "a.txt"&& (sed -i '/angeltoto/c\'"angeltoto=BUPT" &quo ...

  9. QT5.3无法自动调用incomingConnection函数的问题(4.7没有这个问题)

    最近将qt4.7的一个工程移到5.3,遇到了几个麻烦事,主要是这个incomingConnection监听后无法自动调用的问题,在4.7上是完全没有问题的,到了5.3就不行,网上也查了下,网友们都是放 ...

  10. Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏

    原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session--Make your app fanc ...