目录

  • 双数组trie树的构建
    • 构建base array
    • 构建check array
  • 双数组trie树的查询

双数组trie树的构建

NLP中trie树常用于做快速查询,但普通的trie树由于要保存大量的节点信息,当储存的词量非常大时,不仅所占空间巨大,而且查询的速度也不够快。而双数组trie树就可以比较好的解决这两个问题。

之所以叫双数组trie树,是因为它只用base[]check[]两个数组就将整个trie的信息储存了起来,这两个数组的构建规则是:
b a s e [ i ] + c o d e ( x ) = j c h e c k [ j ] = i \begin{aligned} &base[i] + code(x) = j\\ &check[j] = i \end{aligned} ​base[i]+code(x)=jcheck[j]=i​
其中i,j都是base array的index,base array的长度是trie树中节点的个数,每个节点在base array中都有一个对应的index。

  • base[]数组用于记录跳转结构, base array中index为i的那个节点,如果按照字符x转移,会转移到index为j的节点
  • check[]数组用于 标识出 base array 中每个状态的前一个状态,其主要作用是检验按base做转移的转移正确性
  • code(x)是字符x的编码,现实中为了方便通常直接用char code

构建base array

下面我们看一个例子来学习base array的构建方法:

现在有“清华”、“清华大学”、“清新”、“中华”、“华人”五个词,构成的trie树如下图所示:

假设例树的字符编码表为:

char
code 1 2 3 4 5 6 7

初始化root的base index为0,base值记为1。首先看root的所有子节点"清,中,华":

  • base[0] + code(清) = 2,此时位置2空闲,因此“清”放入位置2
  • base[0] + code(中) = 7,此时位置7空闲,因此“中”放入位置7
  • base[0] + code(华) = 3,此时位置3空闲,因此“华”放入位置3

目前base array的情况如下:

position 0 1 2 3 4 5 6 7 8 9 10
char root
base 1
  • 每次遍历完一个节点的所有子节点,只可以确认当前节点的base值,以及它的子节点的index位置
  • 子节点的base值此时会默认继承当前节点的base值,但在遍历子节点的子节点时,一旦有冲突,子节点的base值就会做相应修改

接下来遍历第二层的节点"华,新,华,人":

  • base[2] + code(华) = 3,冲突!因此 base[2] 修改为2;base[2] + code(华) = 4,可用,因此 “清华” 放入位置4
  • base[2] + code(新) = 7,冲突!因此 base[2] 修改为3;base[2] + code(新) = 8,可用,因此 “清新” 放入位置8
  • 因为base[2] 再次北被修改,所以“清华”的位置要重新计算:base[2] + code(华) = 5,可用,因此 “清华” 放入位置5
  • base[7] + code(华) = 3,冲突!因此 base[7] 修改为2;base[7] + code(华) = 4,可用,因此 “中华” 放入位置4
  • base[3] + code(人) = 8,冲突!因此 base[3] 修改为2;base[3] + code(人) = 9,可用,因此 “华人” 放入位置9

目前base array的情况如下:

position 0 1 2 3 4 5 6 7 8 9 10
char root 中华 清华 清新 华人
base 1 3 2 2

接下来遍历第三层的节点"大":

  • base[5] + code(大) = 6,可用;因此 “清华大” 放入位置6

目前base array的情况如下:

position 0 1 2 3 4 5 6 7 8 9 10
char root 中华 清华 清华大 清新 华人
base 1 3 2 2 3

接下来遍历第四层的节点"学":

  • base[6] + code(学) = 7,冲突!base[6] 修改为4;base[6] + code(学) = 8,还是冲突!base[6] 修改为5;base[6] + code(学) = 9,还是冲突!base[6] 修改为6;base[6] + code(学) = 10,可用,因此 “清华大学” 放入位置10

目前base array的情况如下:

position 0 1 2 3 4 5 6 7 8 9 10
char root 中华 清华 清华大 清新 华人 清华大学
base 1 3 2 6 2 3

此时节点已经遍历完,剩余base值未确定的都是尾节点了,因为它们都没用子节点了,所以不存在位置冲突,因此可以直接继承父节点的base值

position 0 1 2 3 4 5 6 7 8 9 10
char root 中华 清华 清华大 清新 华人 清华大学
base 1 3 2 2 3 6 2 3 2 6

构建check array

check array的构建比较简单,只需要将子节点index的check值设为父节点的position值即可,所以有:

position 0 1 2 3 4 5 6 7 8 9 10
char root 中华 清华 清华大 清新 华人 清华大学
base 1 3 2 2 3 6 2 3 2 6
check -2 0 0 7 2 5 0 2 3 6

双数组trie树的查询

此时如果有一个词“清中”,我们要查询它是否在双数组trie里面,那么首先从root出发,由于“清”的code是1,因此会走到 base[0]+code(清) = 2,这里要用check数组检查位置3上的节点其父节点是否是位置0上的节点:check[2] = 0,等式成立!

然后继续看“中”:base[2]+code(中) = 9,再检查位置9上的节点的父节点是否是位置2上的节点:check[9] = 3 !=2 ,检查发现不满足,因此"清中"不在该trie里面。


Reference:
小白详解 Trie 树
double-array-trie双数组trie树原理解析和数据构建过程

双数组trie树详解相关推荐

  1. Trie树详解及其应用

    原文:http://blog.csdn.net/hackbuteer1/article/details/7964147 Trie树详解及其应用

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

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

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

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

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

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

  5. python Trie树和双数组TRIE树的实现. 拥有3个功能:插入,删除,给前缀智能找到所有能匹配的单词...

    #coding=utf-8 #字典嵌套牛逼,别人写的,这样每一层非常多的东西,搜索就快了,树高26.所以整体搜索一个不关多大的单词表 #还是O(1). ''' Python 字典 setdefault ...

  6. 自然语言--Trie树详解及其应用

    链接:http://blog.csdn.net/hackbuteer1/article/details/7964147 参考链接:https://segmentfault.com/a/11900000 ...

  7. 关于双数组Trie查询词典构造总结

    原贴:http://www.firtex.org/firtex_forum/archiver/?tid-241.html FirteX开发论坛 » FirteX开发者专区 » 关于双数组Trie查询词 ...

  8. 用Python实现字典树(Trie)与双数组字典树(DATrie)

    1. 字典树(Trie) 假如我们把字典中的词以记录的形式(无序)存入数据库中.现给定一串字符,要查找该字符串是否为字典中的词.因为数据库中的记录是无序的,所以,最朴素的方法就逐记录匹配.此方法简单, ...

  9. 主线剧情-番外02-设备树详解

    设备树详解 本文 续接 <[主线剧情03]NXP i.MX 系列 u-boot 移植基础详解> 一文中移植过程小节中有关设备树的内容. 编辑整理 By Staok,如有错误恭谢指出,侵删. ...

最新文章

  1. 齐鲁师范学院计算机专业在那个校区,齐鲁师范学院有几个校区及校区地址 哪个校区最好...
  2. 立体匹配之NCC算法
  3. liuux/ Unix 文件管理命令(三)
  4. C++ Primer 5th笔记(chap 15 OOP)抽象基类
  5. 明明一样的程序为啥有的系统就报错有的就正常运行呢_SurfaceGo Android系统折腾笔记...
  6. linux内核态获取ip地址,Linux内核支持动态获取IP地址
  7. JAVA输出两个顺序链表的并集_(顺序表)两个集合求并集-洋葱先生-杨少通
  8. Timer的schedule和scheduleAtFixedRate方法的区别解析(转)
  9. [转载]Qt之模型/视图(自定义风格)
  10. iOS开发之iPhone手机轻松获取UDID的六种方式
  11. 常用遥感数据下载地址
  12. 通用的《求职信》范文模板
  13. 怎么在桌面添加windows便签记事本
  14. 只能选择分卷文件的第一部分_2021学年高一数学新教材必修第一册精讲精练培优讲义(更新第4章,网盘免费下)...
  15. ElasticsearchTemplate的详细使用,完成多条件查询、匹配度查询等
  16. worldpress php7.2,centos7.4下word press环境由php5.6.4升级到php7.2
  17. 05.抽象队列同步器AQS应用之Lock详解
  18. CSAPP lab2 经典的bomblab二次学习
  19. Java打怪升级道路
  20. qq 4 android,Android QQ HD v5.5.4 正式版发布

热门文章

  1. Git-版本控制,GitHub,Git分支
  2. echarts折线图区域渐变
  3. appium+python爬取其他人微信朋友圈(二)
  4. 关于iView UI的表单Form如何进行前端验证
  5. 【回溯算法】【打卡第179道】:leetCode :39. 组合总和(数组中的元素可以重复使用)
  6. LVDS,CML,LVPECL,VML之间接口电平转换(来自TI文档)
  7. 如何更改一个特定提交的提交作者?
  8. 如何在Word里的字母上方添加特殊符号——“拼音指南”+“切换域代码”完美解决!
  9. 直角坐标,柱坐标,球坐标变换
  10. 企鹅电竞将终止运营:含着金钥匙诞生 却被腾讯舍弃