秉着能偷懒就偷懒的精神,关于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. 简约的单页应用引擎:sonnyJS

    点这里 SonnyJS是一个简约的单页应用引擎和HTML预处理器,旨在帮助开发人员和设计人员创建难以置信的强大和快速的单页网站. 主要特性: 模板嵌套,模板继承 动态同步模板路由(非Ajax) 跨窗口 ...

  2. iOS多线程的初步研究(七)-- dispatch对象

    谈起iOS的dispatch(正式称谓是Grand Central Dispatch或GCD),不得不说这又是iOS(包括MacOSX)平台的创新,优缺点这里不讨论,只有当你使用时才能真正体会到.我们 ...

  3. java 关于mysql

    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after co ...

  4. Linux网络编程6——使用TCP实现文件服务器

    需求 当客户端连接上服务器后,服务器会将相应文件传输给客户端,实现文件下载. 思路 服务器端,主进程负责listen.循环内,主进程每从任务请求队列中accept出一个请求,就fork出孙子完成文件传 ...

  5. php 修改 AppServ 下Apache 端口

    php 修改 AppServ 下Apache 端口 步骤一:把 C:\AppServ\Apache2.2\conf 中httpd.conf修改了 还不正确 步骤二:把httpd.conf  中List ...

  6. 内存就是RAM?

    内存不全是RAM,让我们看看当今的Intel计算机是如何连接各个组件的吧.下图展示了主板上的主要组件: 现代主板的示意图,北桥和南桥构成了芯片组. 当你看图时,请牢记一个至关重要的事实:CPU一点也不 ...

  7. web.xml文件中加载顺序的优先级

    在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...

  8. Java-马士兵设计模式学习笔记-责任链模式-FilterChain功能

    一.目标 增加filterchain功能 二.代码 1.Filter.java public interface Filter { public String doFilter(String str) ...

  9. 使用RedisTemplate的操作类访问Redis(转)

    深入理解Spring Redis的使用 (三).使用RedisTemplate的操作类访问Redis 事务需要开启enableTransactionSupport,然后使用@transactional ...

  10. IDEA中利用JUnit进行单元测试

    打开IntelliJ IDEA工具,Alt+Ctrl+S,打开设置窗口,点击进入Plugins. 从插件资源库中搜索JunitGenerator V2.0版本