汉语词典快速查询算法研究概要
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
汉语词典快速查询算法研究
李江波周强陈祖舜
(清华大学智能技术与系统国家重点实验室北京100084)
E-mail:********************.cn
摘要:汉语词典查询是中文信息处理系统的重要基础部分,对系统效率有重要的影响。本文对汉语词典查询算法研究作了简要回顾,设计实现了基于双数组TRIE机制的汉语词典查询算法,并提出了基于双编码机制的词典查询算法。最后对两种词典查询机制进行了实验分析。
关键词:汉语词典查询;双数组TRIE;双编码;中文信息处理。
一、引言
在汉语信息处理系统中,汉语词典查询是一个重要的基础环节,在整个处理过程中都需要频繁地访问词典以获得汉语词语知识,因而汉语词典的快速查询是整个处理系统效率的关键所在。针对词典查询方法,前人作了大量工作,并形成了许多汉语词典组织结构和相应的查询算法。
早期的词典组织构造主要是基于传统Hash方法,文献[1]中采用的方法就是一个典型应用,这种方法的关键技术是Hash函数的设计,采用合理的方式来调节数据块的分配,控制分布的均匀性,减少冲突,提高空间利用率,由于涉及到磁盘读取,这种方法在速度上存在较大局限。
文献[2]指出了三种典型的词典查询方法:整词二分法、TRIE索引树法、逐字二分法。以下分别对这三种方法作简要介绍:(1)基于整词二分的词典机制:整词二分方法的词典结构分为词典正文、词索引表、首字散列表等三级。通过首字散列表的哈希定位和词索引表,很容易确定指定词在词典正文中的可能位置范围,进而在词典正文中通过整词二分进行定位。这种算法的数据结构简单、占用空间小,构建及维护也简单易行,但由于采用全词匹配的查询过程,效率较为低下。(2)基于TRIE索引树的词典机制:TRIE索引树是一种以树的多重链表形式表示的键树,基于TRIE索引树的词典机制由首字散列表和TRIE索引树结点两部分组成。TRIE索引树的优点是分词应用中,在对被切分语句的一次扫描过程中,不需预知待查询词的长度,沿着树链逐字匹配即可;缺点是它的构造和维护比较复杂,而且都是单词树枝,浪费了一定的空间。(3)基于逐字二分法的查询机制:基于逐字二分法的查询机制是对前两种词典机制的改进方案,一方面,从组织结构上,逐字二分与整词二分的词典结构完全一样;另一方面,逐字二分吸收了TRIE索引树的查询优势,即采用的是“逐字匹配”,而不是整词二分的“全词匹配”,这就一定程度地提高了匹配的效率。但由于采用的仍是整词二分的词典结构,使效率的提高受到很大的局限。
文献[3]中提出了基于双字哈希机制的词典查询方法,该方法主要结合了词典中的多字词条(3字词以上)数量少,使用频度低的特点,对基于TRIE索引树的词典机制做出了改进,把TRIE索引树的深度限制为2。其三层结构分别是首字哈希索引,次字哈希索引,剩余字串组。这种查询机制相当于使2字词以下的短词用TRIE索引树机制实现,3字词以上的长词的剩余部分用线性表组织,从而避免了深度搜索,一定程度上提高了查询性能。
此外,文献[4]中提出了一种基于PA TRICIA tree的汉语词典查询机制,这种方法首先使用词条的内码来作为一个关键词位串,然后通过位串比较构造出PATRICIA tree树,树的每个内部节点包括三个数据项:比较位、左指针、右指针,树的叶子节点代表一个词条。查询时根据内部节点选择后继路径,直到叶子节点,该方法的优点是引入了位比较,但是因为树的构造过程是基于内码而非字的,所以不可避免地导致树的深度大大增加,从而造成了效率
降低和空间浪费。
本文设计实现了基于双数组Trie(Double-Array Trie)原理的汉语查询词典;提出并实现了一种基于双编码机制的词典查询机制;最后对改进二分法,双数组Trie(Double-Array Trie),双编码方法三种方法进行了性能上的比较。下面的第二章介绍双数组Trie (Double-Array Trie)的数据结构和具体实现,第三章介绍双编码方法的编码思想和具体查询方式,第四章是对双编码思想进行的性能分析,第五章是对三种方法进行性能实验分析,第六章为全文的总结。
二、双数组Trie(Double-Array Trie)的数据结构与具体实现
Trie树是搜索树的一种,来自英文单词"Re trie val"的简写,可以建立有效的数据检索组织结构。Trie树本质上是一个确定的有限状态自动机(DFA),每个节点代表自动机的一个状态,根据变量的不同,进行状态转移,当到达结束状态或者无法转移的时候,完成查询。传统上的DFA一般用转换表方式来实现,表的列代表自动机的不同状态,行代表转换变量,但是对于词典查询来说,转换表的问题是数据稀疏导致严重地的空间浪费,其空间复杂度为O(n2)。Trie树的另一种实现方式是使用链表节点,这种方式在空间复杂度上降低为O(n),但是问题在于数据结构复杂,查询效率较低[5]。
为了让Trie实用的实现算法在空占用间较少的同时还要保证查询的效率,前人提出了一种用4个线性数组表示DFA的方法,并进一步提出了用3个线性数组表示Trie树的方式。在此基础上,文献[6]做出了进一步改进,用2个线性数组来进行Trie树的表示,即双数组Trie(Double-Array Trie)[7]。
双数组Trie(Double-Array Trie)由两个整数数组构成,一个是base[],另一个是check[]。设数组下标为i ,如果base[i],check[i]均为0,表示该位置为空。如果base[i]为负值,表示该状态为词语。Check[i]表示该状态的前一状态,t=base[i]+a, check[t]=i 。对于汉字词典,采用相同的思想。先把双数组的1-6768放置6768个常用汉字。对于每一个汉字,确定一个base 值,使得对于所有以该汉字开头的词,在双数组中都能放下。例如,现在要确定“阿”字的base值,假设以“阿”开头的词的第二个字序列码依次为a1,a2,a3……an,我们必须找到一个值i,使得base[i+a1],check[i+a1],base[i+a2],check[i+a2]……base[i+an],check[i+an]均为0。一旦找到了这个i,“阿”的base值就确定为i。对于第二个字,第三个字也是类似。
双数组构造完成以后,查询起来极为方便。待查词有几个字,就将汉字分别转换为对应的序列码,然后作几次加法,即可查到相应的词语,无须折半查找。由于汉语中常用词平均长度不到3个字,因此双数组查询算法的效率是极高的。
下面举例说明双数组Trie(Double-Array Trie)的构造过程和查询过程。假定词表中只有“啊,阿根廷,阿胶,阿拉伯,阿拉伯人,埃及”这几个词,用Trie树可以表示为: