Trie树分词
http://www.hankcs.com/program/java/tire-tree-participle.html
最近在看Ansj中文分词的源码,以前没有涉足过这个领域,所以需要做一些笔记。
Trie树
首先是Ansj分词最基本的数据结构——Trie树。Trie树也称字典树,能在常数时间O(len)内实现插入和查询操作,是一种以空间换取时间的数据结构,广泛用于词频统计和输入统计领域。
Ansj作者ansjsun为此数据结构专门开了一个项目,clone下来之后可以用作者提供的一个demo进行测试:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
package com.hankcs;import love.cq.domain.Forest;import love.cq.library.Library;import love.cq.splitWord.GetWord;import java.io.BufferedReader;import java.io.StringReader;/** * @author hankcs */public class Main{ public static void main(String[] args) throws Exception {/** * 词典的构造.一行一个词后面是参数.可以从文件读取.可以是read流. */ String dic = "中国\t1\tzg\n" + "人名\t2\n" + "中国人民\t4\n" + "人民\t3\n" + "孙健\t5\n" + "CSDN\t6\n" + "java\t7\n" + "java学习\t10\n"; Forest forest = Library.makeForest(new BufferedReader(new StringReader(dic))); /** * 删除一个单词 */ Library.removeWord(forest, "中国"); /** * 增加一个新词 */ Library.insertWord(forest, "中国人"); String content = "中国人名识别是中国人民的一个骄傲.孙健人民在CSDN中学到了很多最早iteye是java学习笔记叫javaeye但是java123只是一部分"; GetWord udg = forest.getWord(content); String temp = null; while ((temp = udg.getFrontWords()) != null) System.out.println(temp + "\t\t" + udg.getParam(1) + "\t\t" + udg.getParam(2)); }} |
输出:
|
1
2
3
4
5
6
7
|
中国人 null null中国人民 null null孙健 null null人民 null nullCSDN null nulljava学习 null nulljava null null |
这段demo的目的是利用一个小词典对后面一句话进行分词,词典被用来构造了一颗Trie树,也就是代码中的forest。
词典每一行第一列是单词,之后的几列都是param(属性)。

在tree_split中,一棵Trie树有四种不同的节点:
根节点,上图的绿色节点。被称为Forest,没有实际含义,也不含属性。
起始节点,上图的蓝色节点。是一个单词的开头第一个字,不含属性。
中继节点,上图的黄色节点。可能是一个单词的结尾,含属性;也可能是另一个更长的单词的中间某个字,不含属性。
结束节点,上图的红色节点。是一个单词的结尾,含属性。
根节点使用Forest描述,而其它三种节点统一使用Branch描述,并用status = 1 2 3 来区分,它们有如下的类图关系:

Root在构造的时候开了212个空槽以供放置子节点,每个汉字和其他字符都落在这个范围内。每次查找直接用汉字作为下标即可定位,Branch则使用动态数组分配内存,使用二分查找定位,这是Trie树的高速秘诀。Trie树的查询和插入都是类似的方法:从根节点开始沿着词语的开头字符走到结尾字符。在这里除了完成基本的维护操作,还需维护Branch的status。
删除操作比较讨巧,统一将要删除的单词最后一个字对应的节点设为“起始节点”,那么它就不能构成这个词了。
词典分词
词典分词是一种实现简便、速度快但是错误率高的分词方式。用Trie树词典分词就是按照句子的字符顺序从root往下走,每走到一个结束节点则分出一个词。中途遇到的中继节点统统忽略,这种方式也称“最长匹配”,是一种很武断的方式。比如下面这个例子:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package com.hankcs;import love.cq.domain.Forest;import love.cq.library.Library;import love.cq.splitWord.GetWord;import java.io.BufferedReader;import java.io.StringReader;/** * @author hankcs */public class Main{ public static void main(String[] args) throws Exception {/** * 词典的构造.一行一个词后面是参数.可以从文件读取.可以是read流. */ String dic = "商品\t1\tzg\n" + "和服\t2\n" + "服务\t4\n" ; Forest forest = Library.makeForest(new BufferedReader(new StringReader(dic))); String content = "商品和服务"; GetWord udg = forest.getWord(content); String temp = null; while ((temp = udg.getFrontWords()) != null) System.out.println(temp + "\t\t" + udg.getParam(1) + "\t\t" + udg.getParam(2)); }} |
输出:
|
1
2
|
商品 zg null和服 null null |
很明显,效果不好。
要想提高分词效果,就必须引入条件概率(隐马尔可夫模型),这就是Ansj分词的使命吧。
Trie树分词的更多相关文章
- Ansj分词双数组Trie树实现与arrays.dic词典格式
http://www.hankcs.com/nlp/ansj-word-pairs-array-tire-tree-achieved-with-arrays-dic-dictionary-format ...
- [转]双数组TRIE树原理
原文名称: An Efficient Digital Search Algorithm by Using a Double-Array Structure 作者: JUN-ICHI AOE 译文: 使 ...
- 双数组Trie树 (Double-array Trie) 及其应用
双数组Trie树(Double-array Trie, DAT)是由三个日本人提出的一种Trie树的高效实现 [1],兼顾了查询效率与空间存储.Ansj便是用DAT(虽然作者宣称是三数组Trie树,但 ...
- trie树信息抽取之中文数字抽取
这一章讲一下利用trie树对中文数字抽取的算法.trie树是一个非常有用的数据结构,可以应用于大部分文本信息抽取/转换之中,后续会开一个系列,对我在实践中摸索出来的各种抽取算法讲开来.比如中文时间抽取 ...
- 双数组trie树的基本构造及简单优化
一 基本构造 Trie树是搜索树的一种,来自英文单词"Retrieval"的简写,可以建立有效的数据检索组织结构,是中文匹配分词算法中词典的一种常见实现.它本质上是一个确定的有限状 ...
- 从Trie树到双数组Trie树
Trie树 原理 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,能在常数时间O(len)内实现插入和查 ...
- python Trie树和双数组TRIE树的实现. 拥有3个功能:插入,删除,给前缀智能找到所有能匹配的单词
#coding=utf- #字典嵌套牛逼,别人写的,这样每一层非常多的东西,搜索就快了,树高26.所以整体搜索一个不关多大的单词表 #还是O(). ''' Python 字典 setdefault() ...
- 双数组Trie树(DoubleArrayTrie)Java实现
http://www.hankcs.com/program/java/%E5%8F%8C%E6%95%B0%E7%BB%84trie%E6%A0%91doublearraytriejava%E5%AE ...
- 数据结构 | 30行代码,手把手带你实现Trie树
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法和数据结构专题的第28篇文章,我们一起来聊聊一个经典的字符串处理数据结构--Trie. 在之前的4篇文章当中我们介绍了关于博弈论的 ...
随机推荐
- 查看APP的下载量
开发者账号登陆后:→用户中心→iTunes Connect→Sales Trend
- R基础学习(一)-- 连接mysql数据库
测试环境:win10+RStudio (1)在Console加载两个插件 >install.packages('DBI') Installing package into ‘C:/Users/l ...
- CCCC 成都信息工程大学游记
晚上刷智障25人本,刷到深夜四点,然后迷迷糊糊8点钟起床上车睡觉,然后就到了信息工程大学. 然后开始抢衣服,抢完衣服就开始拍照. 对了,这个学校看了下地图,好小呀,不过妹子好多呀. 然后就被老师带进机 ...
- 研究table-cell和overflow
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- CentOS下的apache配置支持php
修改Apache的配置文件httpd.conf(vi /etc/httpd/conf/httpd.conf) DirectoryIndex index.html index.php #添加index. ...
- IIS7.0下 HTTP 错误 404.15 - Not Found 请求筛选模块被配置为拒绝包含的查询字符串过长的请求
IIS7.0下 HTTP 错误 404.15 - Not Found 请求筛选模块被配置为拒绝包含的查询字符串过长的请求 IIS7.0下查询条件太多时,会报错,因为IIS 7对于Query Str ...
- eclipse使用内置tomcat和使用外部tomcat的设置
近期由于项目中jsp发请求要訪问项目以外的文件.直接訪问写成"c:\xxx\xxx.mp4"来訪问是没有权限的.不能完毕现有要求.经查询后发现能够在tomcat中配置虚拟文件夹将本 ...
- Android之 MTP框架和流程分析
概要 本文的目的是介绍Android系统中MTP的一些相关知识.主要的内容包括:第1部分 MTP简介 对Mtp协议进行简单的介绍.第2部分 MTP框架 介绍 ...
- NSZombie 详解 -僵尸对象
1.什么是僵尸对象? 简而言之,就是过度释放的对象. 2.僵尸对象有什么特点? 如果一个对象a被变成了僵尸对象,那么,在进行下面的判断时,a是会被系统当成一个对象来进行判断的.但是,如果你使用a进行其 ...
- C#编程(五十六)----------可观察的集合ObservableCollection
原文链接: http://blog.csdn.net/shanyongxu/article/details/47080685 可观察的集合 如果需要集合中的元素核实删除或添加的信息,就可以使用Obse ...