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

原创 2013年12月02日 08:23:10

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

正则表达式的最短与最长匹配

贪婪与懒惰 当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。考虑这个表达式:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它...
  • waysoflife
  • waysoflife
  • 2015年01月31日 10:23
  • 4505

IP路由查找的“最长匹配原则”

最长匹配原则是CISCO IOS路由器默认的路由查找方式。当路由器收到一个IP数据包时,会将数据包的目的IP地址与自己本地路由表中的表项进行bit by bit的逐位查找,直到找到匹配度最长的条目,这...
  • CeeLo_Atom
  • CeeLo_Atom
  • 2015年07月31日 09:10
  • 6835

逆向最长匹配算法的实现

   中文分词技术属于自然语言处理技术范畴,对于一句话,人可以通过自己的知识来明白哪些是词,哪些不是词,但如何让计算机也能理解?其处理过程就是分词算法。现有的分词算法可分为三大类:基于字符串匹配的分词...
  • yaoxy
  • yaoxy
  • 2009年06月22日 10:59
  • 1150

1998年人民日报语料库,词的最长,最短匹配 提取问题,

由于语料中包括 [中央/n 人民/n 广播/vn 电台/n]nt 此类词问题,可以选择最长词提取,也可以选择最短词提取 # -*- coding: utf-8 -*- impo...
  • u013378306
  • u013378306
  • 2017年03月08日 18:06
  • 334

正则表达式的最短与最长匹配

贪婪与懒惰 当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。考虑这个表达式:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它...
  • waysoflife
  • waysoflife
  • 2015年01月31日 10:23
  • 4505

正确匹配的最长的括号子串

题目:有个由’(’和’)’组成的字符串,求出其中最长的正确匹配子串,如((()()中是()() 分析:使用字符串进出栈来模拟括号的匹配,栈中保存没有进行匹配的字符串,扫描字符串,对于第i个字符,如果...
  • Cindy_zhong
  • Cindy_zhong
  • 2013年08月28日 14:25
  • 1244

Java实现的最大匹配法统计词频

  • 2009年04月07日 10:11
  • 959KB
  • 下载

问答系统(QA)1—基于词典的正向最大匹配算法

转载:杨尚川 地址:http://yangshangchuan.iteye.com/blog/2031813 内容有修改 基于词典的正向最大匹配算法(最长词优先匹配),算法会根据词典文件自动调整最大长...
  • Elmo66
  • Elmo66
  • 2016年12月01日 11:06
  • 1054

python实现前向匹配中查找最大长度的最高重复模式的子字符串

之前写过一篇文章是:python获取指定字符串中重复模式最高的字符串     在这里的方法很简单无非就是一个滑窗,重叠的滑动,将字符串所有的可能都找到,然后统计一下即可,现在我要的是前向匹配最大长度...
  • Together_CZ
  • Together_CZ
  • 2017年07月11日 22:33
  • 991

Trie树(字典树)实现词频统计或前缀匹配类型的问题

一:概念      如果我们有and,as,at,cn,com这些关键词,那么trie树(zidianshu)? 从上面的图中,我们或多或少的可以发现一些好玩的特性。    ...
  • Sup_Heaven
  • Sup_Heaven
  • 2014年10月15日 15:31
  • 5195
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:中文分词-最长匹配法的实现
举报原因:
原因补充:

(最多只允许输入30个字)