浏览 1394 次
锁定老帖子 主题:庖丁分词的源码分析 (4) 分词过程
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2013-04-09
庖丁分词的主要分词实现是CJKKnife,主要的方法是dissect方法。但是这个方法300多行,我不想全部贴出来。我选一些重点说说。dissect首先会用到assignable方法,其实就是找到要分词的对象,这里主要是中文。遇到不是中文的就强行截断了,后面的再继续开始。
/** * 分解以CJK字符开始的,后可带阿拉伯数字、英文字母、横线、下划线的字符组成的语句 */ public int assignable(Beef beef, int offset, int index) { char ch = beef.charAt(index); if (CharSet.isCjkUnifiedIdeographs(ch)) return ASSIGNED; if (index > offset) { if (CharSet.isArabianNumber(ch) || CharSet.isLantingLetter(ch) || ch == '-' || ch == '_') { return POINT; } } return LIMIT; } GO_UNTIL_LIMIT: while (true) { switch (assignable(beef, offset, limit)) { case LIMIT: break GO_UNTIL_LIMIT; case POINT: if (point == -1) { point = limit; } } limit++; } 如果从字典找到有: if (curSearch.isHit()) { if (!word.isNoise()) { collector.collect(word.getText(), curSearchOffset, curSearchEnd); } } [size=large] 把这个放到结果容器里去,当然这个容器还会再处理,就是最长和最多的分词实现,这个下篇文章会细说。 其实这个已经是分词的主要实现了,去找字典,找到的就切分出来,找不到字典的怎么办: dissectIsolated(collector, beef, maxDicWordEnd, offsetLimit); 这个方法执行的就是两个字一分而已。 当然还有处理“”《》这些特殊情况的:[/size] int len = limit - offset; if (len > 2 && len != maxDicWordLength && shouldBeWord(beef, offset, limit)) { collector.collect(beef.subSequence(offset, limit).toString(), offset, limit); } 这样其实整个过程就完了,但是如何尽早确定这个词不在字典里,这个很关键,这个就用到了上篇文章说的,字典查询返回的几个状态了: // 若isolatedFound==true,表示词典没有该词语 boolean isolatedFound = curSearch.isUndefined(); // 若isolatedFound==false,则通过Hit的next属性检视词典没有beef的从offset到curWordEnd // + 1位置的词 // 这个判断完全是为了减少一次词典检索而设计的, // 如果去掉这个if判断,并不影响程序的正确性(但是会多一次词典检索) if (!isolatedFound && !curSearch.isHit()) { isolatedFound = curSearchEnd >= limit || beef.charAt(curSearchEnd) < curSearch.getNext() .charAt(curSearchLength); } // 2) // 词汇表中没有该词语,且没有以该词语开头的词汇... // -->将它记录为孤立词语 if (isolatedFound) { 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |