搜索引擎中文分词原理与实现

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

while (ts.i ncreme ntToke n()) {

//取得下一个词

搜索引擎中文分词原理与实现

因为中文文本中,词和词之间不像英文一样存在边界, 所以中文分词是一个专业处理中

文信息的搜索引擎首先面对的问题,需要靠程序来切分出词。 一、LUCene 中的中文分词

LUCene 在中处理中文的常用方法有三种,以 皎死猎人的狗"为例说明之:

单 字:【咬】

【死】 【猎】 【人】 【的】 【狗】

二元覆盖:【咬死】 【死猎】 【猎人】 【人的】 【的狗】

词:【咬】 【死】 【猎人】 【的】

【狗】

LUCene 中的StandardTokenizer 采用单子分词方式, CJKTokenize 采用二元覆盖方式。 1、LUCene 切分原理

LUCene 中负责语言处理的部分在 org.apache.Iucene.analysis 包,其中, TokenStream 类 用来进行基本的分词工作, Analyzer 类是TokenStream 的包装类,负责整个解析工作,Analyzer 类接收整段文本,解析出有意义的词语。

通常不需要直接调用分词的处理类 analysis ,而是由LUCene 内存内部来调用,其中:

(1) 在索引阶段,调用 addDocument (doc )时,LUCene 内部使用 Analyzer 来处理每 个需要

索引的列,具体如下图:

图1 LUCene 对索引文本的处理

In dexWriter in dex = new In dexWriter(i ndexDirectory, new CnAn alyzer(), //用于支持分词的分析

器 !in Creme ntal,

In dexWriter.MaxFieldLe ngth.UNLIMITED);

(2) 在搜索阶段,调用

QUeryParSer.parse (queryText )来解析查询串时, QUeryParSer 会调用Analyzer 来拆分查询字符串,但是对于通配符等查询不会调用 Analyzer 。

An alyzer an alyzer = new CnAn alyzer();

//支持中文的分词

QUeryParSer ParSer = new QUeryParSer(VerSiO n.L UCENE_CURRENT, "title", an alyzer); 因为在索引和搜索阶段都调用了分词过程,索引和搜索的切分处理要尽量一致,所以 分词效果改变后需要重建索引。

为了测试LUCene 的切分效果,下面是直接调用 Analysis 的例子: Analyzer analyzer = new CnAnalyzer();

// 创建一个中文分析器

TokenStream ts = analyzer.tokenStream("myfield", new StringReader(" 待切分文本 "));

//

取得Token流

SyStem.out.pri ntln ("toke n: "+ ts);

}

2、LUCene 中的Analyzer

为了更好地搜索中文,通过下图来了解一下在LUCene中通过WhiteSPaCeTOkeniZer、WOrdDeIimiterFiIter、LOWerCaSeFiIter 处理英文字符串的流程:

LeXCorP BFG-9000

Whi te spar eToken i Zer

LeXCorP BFG-9000

Word Deliini terFilter C Cltenale WOrdii= 1

r

LOWerCaSeFiIler

IejtCCrP

图2 LUCene处理英文字符串流程

、查找词典算法

词典格式可以是方便人工查看和编辑的文本文件格式,也可以是方便机器读入的二进

制格式。词典的最基本文本文件格式就是每行一个词。在基于词典的中文分词方法中,词

典匹配算法是基础。一般词典规模都在几十万词以上,所以为了保证切分速度,需要选择一个好的查找词典算法。

1、标准Trie树

一个数字搜索Trie树的一个节点只保留一个字符,如果一个单词比一个字符长,则包

含第一个字符的节点有指针指向下一个字符的节点,依次类推。这样组成一个层次结构的

树,树的第一层包括所有单词的第一个字符,树的第二层包括所有单词的第二个字符,依次

类推,数字搜索树的最大高度是词典中最长单词的长度。比女口:如下单词序列组成的词典(as at be by he in is it Of On Or to )会生成如下图所示的数字搜索树:

图3数字搜索树

数字搜索树的结构独立于生成树时单词进入的顺序,这里,Trie树的高度是2。因为树

的高度很小,在数字搜索Trie树种搜索一个单词的速度很快。但是,这是以内存消耗为代

价的,树中每个节点都需要很多内存。假设每个词都是由26个小写英文字母中的一个组成

的,这个节点中会有26个指针。所以不太可能直接用这样的数字搜索树来存储中文这样的

大字符集。

Trie树在实现上有一个树类( SearChTrie)和一个节点类(TrieNode)。SearChTrie的主要方法有两个:

(1)增加单词到搜索树,方法原型是:addWord ( String word )。

(2)从文本的指定位置开始匹配单词,方法原型是:matchLOng( String text, int OffSet )。2、三叉Trie树

在一个三叉搜索树(Ternary SearCh Trie)中,每一个节点包括一个字符,但和数字搜索树不同,三叉搜索树只有三个指针:一个指向左边的树;一个指向右边的树;还有一个向下,指向单词的下一个数据单元。三叉搜索树是二叉搜索树和数字搜索树的混合体。它有

和数字搜索树差不多的速度但是和二叉搜索树一样只需要相对较少的内存空间。

树是否平衡取决于单词的读入顺序。如果按顺序后的顺序插入,则生成方式最不平衡。

单词的读入顺序对于创建平衡的三叉搜索树很重要,但对于二叉搜索树就不太重要。通过

选择一个排序后数据单元集合的中间值,并把它作为开始节点,我们可以创建一个平衡的三

叉树。如下代码可以用来生成平衡的三叉树词典:

*在调用此方法前,先把词典数组k排好序

* @Param fp写入的平衡序的词典

* @Param k排好序的词典数组

* @Param OffSet 偏移量

* @Param n 长度

* @throws EXCePti On

相关文档
最新文档