关闭

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

标签: c++MT机器翻译最长匹配
609人阅读 评论(0) 收藏 举报
分类:

最长匹配法的基本思想是:设词表中最长的词由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();
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:51060次
    • 积分:1330
    • 等级:
    • 排名:千里之外
    • 原创:84篇
    • 转载:1篇
    • 译文:0篇
    • 评论:6条
    最新评论