您的位置:首页 > 编程语言 > C语言/C++

中文分词-最长匹配法的实现

2013-12-02 08:23 441 查看
最长匹配法的基本思想是:设词表中最长的词由m个字(程序中m=5)组成,每次进行切分时总是从待切分的句子中截取一个长度为m的匹配字段w,查找分词词典。

(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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息