中文分词-最长匹配法的实现
2013-12-02 08:23
441 查看
最长匹配法的基本思想是:设词表中最长的词由m个字(程序中m=5)组成,每次进行切分时总是从待切分的句子中截取一个长度为m的匹配字段w,查找分词词典。
(1)若在词典中,则匹配成功。匹配字段w作为一个新词被切分出来
(2)若不在词典中,则匹配失败,从w中去掉最后一个词,进行新的匹配。如此进行下去,直到匹配成功为止。
如果完成一次匹配就将匹配成功的单词从句子中去掉,按照上述步骤重复进行切分,直至切分完所有的词为止。
最长匹配分为从后往前和从前往后两种形式:程序中采用的是从后往前的形式
举例来说:“中华人民共和国成立了“
(1)拿出后五个词“和国成立了”,查找词典没有找到这个词
(2)然后把“和”去掉,查找“国成立了”,查找词典还是找不到
(3)然后把“国”去掉,查找“成立了”,词典中还是没有
(4)然后把“成”去掉,查找“立了”,词典中还是没有
(5)然后把“立”去掉,只剩一个字了,词典中肯定是有的,即查找到了一个词“了”
(6)把“了”从句子中去掉,句子就剩“中华人名共和国成立”
(7)然后再找出5个词来进行匹配,直到全部都匹配完为止
最后的结果会是 中华/人民/共和国/成立/了 (使用不同的字典,切分出来的结果也是不一样的)
程序中还考虑了数字,连续的数字的处理,实现代码如下:
(1)若在词典中,则匹配成功。匹配字段w作为一个新词被切分出来
(2)若不在词典中,则匹配失败,从w中去掉最后一个词,进行新的匹配。如此进行下去,直到匹配成功为止。
如果完成一次匹配就将匹配成功的单词从句子中去掉,按照上述步骤重复进行切分,直至切分完所有的词为止。
最长匹配分为从后往前和从前往后两种形式:程序中采用的是从后往前的形式
举例来说:“中华人民共和国成立了“
(1)拿出后五个词“和国成立了”,查找词典没有找到这个词
(2)然后把“和”去掉,查找“国成立了”,查找词典还是找不到
(3)然后把“国”去掉,查找“成立了”,词典中还是没有
(4)然后把“成”去掉,查找“立了”,词典中还是没有
(5)然后把“立”去掉,只剩一个字了,词典中肯定是有的,即查找到了一个词“了”
(6)把“了”从句子中去掉,句子就剩“中华人名共和国成立”
(7)然后再找出5个词来进行匹配,直到全部都匹配完为止
最后的结果会是 中华/人民/共和国/成立/了 (使用不同的字典,切分出来的结果也是不一样的)
程序中还考虑了数字,连续的数字的处理,实现代码如下:
#include "iostream" #include "fstream" #include "sstream" #include "string" #include "set" using namespace std; /********************************************************* *函数名:SplitString *参 数: szStr 待切分字符串,result存储切分好的字符串 * chDel 切分字符 *功 能:将字符串按照指定字符进行切分,并将结果存入到数组中 *********************************************************/ void SplitString(string szStr,string result[],char chDel) { string szTemp; int icount = 0; for(int i=0; i<szStr.size();i++) { if(chDel == szStr[i]) { szStr[i] = ' '; } } istringstream stream(szStr); while(stream>>szTemp) { //cout<<szTemp<<endl; result[icount++] = szTemp; } } /************************************************************ *函数名:isCH *参 数:c代表一个字符 *返回值:0代表字符,1代表汉字 *函数功能:判断是汉字还是英文字符 *************************************************************/ int isCH(char c) { if(c&0x80) { return 1; } return 0; } void main() { string szTWord; set<string> szWords; char chTemp[100]; char chSentence[1000]; string szSentence; string szSResult[6]; ifstream fIn("E:\\vc\\seg\\newnihaodic.csv"); //字典 ofstream fOut("E:\\vc\\seg\\dataout.txt"); //输出的切分好的句子 ifstream fInTest("E:\\vc\\seg\\datatest.txt"); //测试语料 if(fIn.is_open() && fOut.is_open() && fInTest.is_open()) { while(!fIn.eof()) { fIn.getline(chTemp,100); SplitString(chTemp,szSResult,','); //cout<<szSResult[0]<<endl; szWords.insert(szSResult[0]); } //默认最大的词中含有5个汉字 while(!fInTest.eof()) { fInTest.getline(chSentence,1000); szSentence = chSentence; int iSize = szSentence.size(); string szSub; int iCount; int iLength; //记录五个字占的长度 while(iSize > 2) { if(iSize>10) { iCount=0; iLength = 0; int i = iSize-1; while(iCount<5) { if(isCH(szSentence[i])) { i-=2; iLength+=2; } else { i--; iLength++; } iCount++; } szSub = szSentence.substr(iSize-iLength,iLength); } else { szSub = szSentence.substr(0,iSize); } while(szSub.size() > 2) { if(szWords.find(szSub) != szWords.end()) { break; } else { if(isCH(szSub[0])) { szSub=szSub.substr(2); } else { szSub=szSub.substr(1); } } } cout<<szSub<<endl; iSize -=szSub.size(); if(isCH(szSub[0])&& (iSize+szSub.size())<szSentence.size()) { if(!isCH(szSentence[iSize+szSub.size()]) && szSentence[iSize+szSub.size()] != '/') { if(iSize != 0) { szSentence.replace(iSize,szSub.size(),"/"+szSub+"/"); } else { szSentence.replace(iSize,szSub.size(),szSub+"/"); } } else { szSentence.replace(iSize,szSub.size(),"/"+szSub); } } } fOut<<szSentence<<endl; } } fIn.close(); fOut.close(); fInTest.close(); }
相关文章推荐
- 关于指针的一些事情
- C/C++数据对齐详细解析
- C++中引用的使用总结
- C++中引用(&)的用法与应用实例分析
- 解析C++ 浮点数的格式化输出
- 深入分析C++中几个最不常用的关键字
- c++中inline的用法分析
- 深入解析C++ Data Member内存布局
- 从汇编看c++中默认构造函数的使用分析
- 关于C++中的友元函数的一些总结
- C++的sstream标准库详细介绍
- 基于C++自动化编译工具的使用详解
- 浅谈C++中的string 类型占几个字节
- C/C++ 宏详细解析
- 深入分析C++中两个大数相乘结果不正确的问题
- 探讨C++中数组名与指针的用法比较分析
- 深入解析C++中的引用类型
- C++可变参数的实现方法
- C++中的常对象与常对象成员详解
- C++类成员构造函数和析构函数顺序示例详细讲解