分词的目的:把一句话,分解成单字、数量词 、词 (分词算法中称为“词元”)
-
初始化词典Trie树结构
-
把句子分解成词
-
处理歧义与冲突词,删除多余的低权重词元
应用目的: 搜索引擎为一段文字建索引,先是把句子折成词然后按词反向索引 文章段落 (称为倒排序索引)
版本:
<dependency>
<groupId>com.janeluo</groupId>
<artifactId>ikanalyzer</artifactId>
<version>2012_u6</version>
</dependency>
测试程序:
public class IKAnalyzerTest {
public static void main(String[] args) {
String str = "这的的确确是一个不折不扣的大优惠";
String word = "告"; // 不成词的单字
String words = "的的确确是";
// System.out.println(segText(str, false));
System.out.println(segText(words, true));
// System.out.println(segText(str, true));
}
private static String segText(String text, boolean useSmart) {
StringBuilder result = new StringBuilder();
IKSegmenter ik = new IKSegmenter(new StringReader(text), useSmart);
try {
Lexeme word = null;
while ((word = ik.next()) != null) {
result.append(word.getLexemeText()).append(" ");
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
return result.toString();
}
}
测试数据:
句子: | 这的的确确是一个不折不扣的大优惠 |
普通分词: | 这 [ 的的确确 的 的确 的 确 确是 ] [一个 一 个] [不折不扣 不折 不扣] 的 大 优惠 |
合并分词: | 这 ( 的 的确 确是 ) 一个 不折不扣 的 大 优惠 |
[]()符号解释: | [ 这里放的是分词后有冲突歧义的词,词与词之间有重叠 ] (合并冲突,删除重复后是没有重叠词的) |
学习过程的疑问:
-
[ 的的确确 的 的确 的 确 确是 ] 的的确确 分词输出后,cursor 已经移动到后面,什么情况下需要回过去把 '的' 这个单字也输出? (Rep:这块是IK分词写的比较好的地方,一次遍历输出所有分词)
-
冲突歧义词合并策略? (Rep:这个问题的解答在下一篇文章)
分解 “的的确确是” 的分词过程:
注:下标为自然语义的数字,下面表格为IKAnalyzer分词器依次描述这5个字的处理步骤与解析过程
描述下标 | 前缀词元列表 tmpHits | 下标范围 | 匹配方式 | 分词结果 orgLexemes |
---|---|---|---|---|
1 | (的) | (0,0) | 前缀 & 单字成词 --> | 的 |
2 | 的(的) | (0,1) | 前缀 | |
(的) | (1,1) | 前缀 & 单字成词 --> | 的 | |
3 | 的的(确) | (0,2) | 前缀 | |
的(确) | (1,2) | 前缀 & 成词 --> | 的确 | |
(确) | (2,2) | 前缀 | ||
4 | 的的确(确) | (0,3) | 词尾 (结束)--> | 的的确确 |
的确(确) | (1,3) | 无法成词(删除) | ||
确(确) | (2,3) | 无法成词(删除) | ||
(确) | (3,3) | |||
5 | 确(是) | (3,3) | 词尾 (结束)--> | 确是 |
(是) | 前缀 (结束,且无法单字成词) |
步骤详述:
状态码: 1 成词,0 词前缀(单字无法成词)
![](https://i-blog.csdnimg.cn/blog_migrate/377b916943193c271f7436e21ee64ee0.png)
- 第一个字 “的” ,即是单字,也是词前缀,所以输出到原始结果集 AnalyzeContext.orgLexemes中,同时不能作为词前缀加入中文分词器的临时词前缀列表中CJKSegmenter.tmpHits,参与到下一个字的前缀匹配。
- 第二个字还是 “的” ,作为单字输出到原始结果集,拼接前面的词前缀 变成 “的的” ,成为新的词前缀参与下一个字的前缀匹配,同时也作为单字前缀加入到前缀列表中。
- 第三个“确”字,根据Trie树判断,“确”字无法单字成词,不加入结果集,可以与前面两个词前缀拼接为新的词前缀 “的的确” 和 “的确” ,“的确” 作为单独词加入结果集。
- 第四个“确”字,单字作为前缀加入前缀列表,与前缀列表中3个前缀再次拼接匹配,其中“的确确”、“确确” 两字无法成词,从前缀列表中删除,“的的确确”作为完整词加入结果集。
此时前缀列表是:[ "确" ] - 最后一个字 “是” ,单字作为前缀加入前缀列表,与前缀列表中前缀拼接为 “确是” ,成为词加入结果集。
此时前缀列表是:[ "是" ] ,但 “的的确确是” 这句子已经遍历完成,所以清空前缀列表。
最后结果集是:[ "的的确确"、"的"、"的确"、"的"、"确是" ]
最后分词结果通过AnalyzeContext#outputToResult 方法输出到最终结果集:
[ "的的确确"、 "的"、 "的确"、 "的"、 "确"、 "确是" ] ,其中句子中第3个字 "确" 作为遗漏单字输出。至此,普通分词完成。