中文分词实现——双向最大匹配
来源:互联网 发布:mac os 重新分区 编辑:程序博客网 时间:2024/06/07 11:03
关于中文分词的一些基本介绍,可以看这篇博客《中文分词方法总结》。这里就不再进行详细介绍了。
双向最大匹配方法
双向最大匹配方法是一种基于词典的分词方法。基于词典的分词方法是按照一定策略将待分析的汉字串与一个“大机器词典”中的词条进行匹配,若在词典中找到某个字符串,则匹配成功。
按照扫描方向的不同:正向匹配和逆向匹配
按照长度的不同:最大匹配和最小匹配
正向最大匹配思想FMM
1.从左向右取待切分汉语句的m个字符作为匹配字段,m为大机器词典中最长词条个数。
2.查找大机器词典并进行匹配。若匹配成功,则将这个匹配字段作为一个词切分出来。
若匹配不成功,则将这个匹配字段的最后一个字去掉,剩下的字符串作为新的匹配字段,进行再次匹配,重复以上过程,直到切分出所有词为止。
逆向最大匹配算法BMM
该算法是正向最大匹配的逆向思维,匹配不成功,将匹配字段的最前一个字去掉,实验表明,逆向最大匹配算法要优于正向最大匹配算法。双向最大匹配法(Bi-directction Matching method,BM)
双向最大匹配法是将正向最大匹配法得到的分词结果和逆向最大匹配法的到的结果进行比较,从而决定正确的分词方法。据SunM.S. 和 Benjamin K.T.(1995)的研究表明,中文中90.0%左右的句子,正向最大匹配法和逆向最大匹配法完全重合且正确,只有大概9.0%的句子两种切分方法得到的结果不一样,但其中必有一个是正确的(歧义检测成功),只有不到1.0%的句子,或者正向最大匹配法和逆向最大匹配法的切分虽重合却是错的,或者正向最大匹配法和逆向最大匹配法切分不同但两个都不对(歧义检测失败)。这正是双向最大匹配法在实用中文信息处理系统中得以广泛使用的原因所在。
在本文实现的方法中,是综合考虑了正向和逆向最大匹配的结果,加入了一些启发式的规则来对分词结果进行进一步消歧的。
启发式规则:
1.如果正反向分词结果词数不同,则取分词数量较少的那个。
2.如果分词结果词数相同
a.分词结果相同,就说明没有歧义,可返回任意一个。
b.分词结果不同,返回其中单字较少的那个。
下面是具体实现
package Segment;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.util.HashSet;import java.util.Set;import java.util.Vector;public class FBSegment {private static Set<String> seg_dict;//加载词典public static void Init(){seg_dict = new HashSet<String>();String dicpath = "data/worddic.txt";String line = null;BufferedReader br;try{br = new BufferedReader( new InputStreamReader( new FileInputStream(dicpath)));while((line = br.readLine()) != null){line = line.trim();if(line.isEmpty())continue;seg_dict.add(line);}br.close();}catch(IOException e){e.printStackTrace();}}/** * 前向算法分词 * @param seg_dict 分词词典 * @param phrase 待分词句子 * @return 前向分词结果 */private static Vector<String> FMM2( String phrase){int maxlen = 16;Vector<String> fmm_list = new Vector<String>();int len_phrase = phrase.length();int i=0,j=0;while(i < len_phrase){int end = i+maxlen;if(end >= len_phrase)end = len_phrase;String phrase_sub = phrase.substring(i, end);for(j = phrase_sub.length(); j >=0; j--){if(j == 1)break;String key = phrase_sub.substring(0, j);if(seg_dict.contains(key)){fmm_list.add(key);i +=key.length() -1;break;}}if(j == 1)fmm_list.add(""+phrase_sub.charAt(0));i+=1;}return fmm_list;}/** * 后向算法分词 * @param seg_dict 分词词典 * @param phrase 待分词句子 * @return 后向分词结果 */private static Vector<String> BMM2( String phrase){int maxlen = 16;Vector<String> bmm_list = new Vector<String>();int len_phrase = phrase.length();int i=len_phrase,j=0;while(i > 0){int start = i - maxlen;if(start < 0)start = 0;String phrase_sub = phrase.substring(start, i);for(j = 0; j < phrase_sub.length(); j++){if(j == phrase_sub.length()-1)break;String key = phrase_sub.substring(j);if(seg_dict.contains(key)){bmm_list.insertElementAt(key, 0);i -=key.length() -1;break;}}if(j == phrase_sub.length() -1)bmm_list.insertElementAt(""+phrase_sub.charAt(j), 0);i -= 1;}return bmm_list;}/** * 该方法结合正向匹配和逆向匹配的结果,得到分词的最终结果 * @param FMM2 正向匹配的分词结果 * @param BMM2 逆向匹配的分词结果 * @param return 分词的最终结果 */public static Vector<String> segment( String phrase){Vector<String> fmm_list = FMM2(phrase);Vector<String> bmm_list = BMM2(phrase);//如果正反向分词结果词数不同,则取分词数量较少的那个if(fmm_list.size() != bmm_list.size()){if(fmm_list.size() > bmm_list.size())return bmm_list;else return fmm_list;}//如果分词结果词数相同else{//如果正反向的分词结果相同,就说明没有歧义,可返回任意一个int i ,FSingle = 0, BSingle = 0;boolean isSame = true;for(i = 0; i < fmm_list.size(); i++){if(!fmm_list.get(i).equals(bmm_list.get(i)))isSame = false;if(fmm_list.get(i).length() ==1)FSingle +=1;if(bmm_list.get(i).length() ==1)BSingle +=1;}if(isSame)return fmm_list;else{//分词结果不同,返回其中单字较少的那个if(BSingle > FSingle)return fmm_list;else return bmm_list;}}}public static void main(String [] args){String test = "我是一个学生";FBSegment.Init();System.out.println(FBSegment.segment(test));}}
输出:[我, 是, 一个, 学生]
了解更详细的信息,可以到这里https://github.com/talentlei/CLSegment
参考:
中文分词算法笔记 http://www.cnblogs.com/lvpei/archive/2010/08/04/1792409.html;
中文分词算法总结 http://blog.csdn.net/chenlei0630/article/details/40710325;
- 中文分词实现——双向最大匹配
- 中文分词 正向最大匹配法 逆向最大匹配法 双向最大匹配法
- 基于N-gram的双向最大匹配中文分词
- 用双向最大匹配法进行中文分词
- 基于N-gram的双向最大匹配中文分词
- 自己动手写分词引擎——逆向最大、正向最大、双向最大分词算法的实现
- 中文分词——正向最大匹配法
- 中文分词——正向最大匹配法
- 中文分词基础原则及正向最大匹配法、逆向最大匹配法、双向最大匹配法的分析
- 中文分词基础原则及正向最大匹配法、逆向最大匹配法、双向最大匹配法的分析
- 中文分词之最大匹配
- 中文分词--逆向最大匹配
- 中文分词--逆向最大匹配
- 【分词】正向最大匹配中文分词算法
- 分词】正向最大匹配中文分词算法
- 【分词】正向最大匹配中文分词算法
- 中文分词-- 正向最大匹配法分词
- 【分词】正向最大匹配中文分词算法
- POJ 1849 Two(遍历树)
- Java基础-将Bean属性值放入Map中
- using thymeleaf 之 th:each迭代循环
- 手写快速排序【随机数作基数】
- hdu 4771 Stealing Harry Potter's Precious(bfs+枚举)
- 中文分词实现——双向最大匹配
- 的个电饭锅
- [jbb0523整理]压缩感知中的数学知识:NP-hard问题
- 日语学习之新版初级标准日本语-6 吉田さんは来月中国へ
- 第10周项目 逗你玩
- hdu2674 N!Again
- 【记中关村.西北食府.兰州拉面】诗一首
- 日语学习之新版初级标准日本语-7 李さんは 毎日 コーヒーを 飲みます
- A. Counterexample