mmseg 中文分词


区别与英文句子,子串,中文汉字之间并没有空格相隔开,所以对于一个汉语的句子来说,如何分词一直也有人在研究,现也有多种根据句子结构,根据词频概率的多种做法,之前因为项目需求需要用到一个中文分词的功能,鉴于时间和功力,就跟网上找了张华平博士的NLPIR中文分词系统,一段时间用还好,可是过段时间之后就完全用不了,错误日志说是因为线程问题,(线程跟时间应该没有关系吧,大概是版权什么的),之后又找了一下编译了一下friso的库文件,但是由于字典文件的路径问题(大神是这么说的),初始化不对,导致分词有误,遂决定自己尝试一下mmseg。
附参考前辈的博文地址 http://blog.csdn.net/sunlylorn/article/details/7652746

大致思路:
首先利用hash_map 构造一个字典 hash_map<WCHAR,vector<BSTR>>,其中vector容器中存放相同词首的词语PS:中国、中国人、中间.blabla....
构造完字典之后根据mmseg的做法
1:首先查找以当前句首词开始的所有的三词chunks
2:根据以下4个规则依次进行筛选
规则1:最大匹配
规则2:最大平均单词长度
规则3:单词长度最小方差
规则4:最大单字单词语素自由度之和

因为涉及词频的查询,最后一步未完成,个人以为,整个算法最关键的地方在于1、词典的构造,词典的大小很大程度决定分词的正确率,2:如何查找以当前句首单词开始的所有chunks这里我用了一个嵌套循环的函数,找到以当前句首开始的所有三词chunks,暂时没有考虑这个词已经是句尾的情况。DicHashmap 就是构造好的汉语字典 

void CWSdic::FindAllTrunks(BSTR str,DicHashmap& dichashmap)
{
	int Count=FindWordsCount(str,dichashmap);//获取到以当前句首词开始的最大词长,
	for(int i=1;i <= Count; i++)
	{
		Chunk newchunk;//new 一个新的chunk
		newchunk.push_back( GetBstrByCount(str,i));
		BSTR str1=str;
//		str1.Delete(0,i+1);
		DeleteNCount(str1,i);
		int Count1 = FindWordsCount(str1,dichashmap);
		for(int j = 1; j<= Count1;j++ )
		{
			Chunk newchunk1(newchunk);//构造的过程,将chunk的元素复制到里面
//			newchunk1.push_back(str1.Left(j));
			newchunk1.push_back(GetBstrByCount(str1,j));
			BSTR str2 = str1;
//			str2.Delete(0,j+2);
			DeleteNCount(str2,j);
			int Count2 = FindWordsCount(str2,dichashmap);
			for(int k=1;k<= Count2;k++)
			{
				Chunk newchunk2(newchunk1);
//				newchunk2.push_back(str2.Left(k));
				newchunk2.push_back(GetBstrByCount(str2,k));
				ChunkList.push_back(newchunk2);			
			}
		}
	}
}

调用过程


BOOL CWSdic::ComflexMaxMatch(DicHashmap& dichashmap,CString ori_str ,vector<CString>& wordvector,int Count)
{
/*
复杂最大匹配:
chen 和liu 认为最大的匹配规则是三个单词:
从句子头部开始,寻找所有三个分词chunks方案。
从一个既定的字符开始,匹配出所有的三个词为一组
的组合。

使用中用四个消除歧义规则,进行过滤直到只存在一种结果
或者四个规则使用完毕。

1、最大匹配:
有两种方案:
简单最大匹配:选择长度最大的词
复杂匹配:选择词组长度最大的那个词组

2、最大平均词语长度:
经过规则1后剩余的词组个数超过1,就选择平均词组长度最大的一个

3、词语长度的最小变化率
词语长度变化率可以由标准差反映,直接套用标准差公式.
标准差=sqrt((x1-x)^2+(x2-x)^2+(x3-x))/3

4、largest sum of degree of mor...涉及统计词频,暂时不考虑

*/
	//BSTR bstr1 = function(ori_str);
	//int bstr1_len = SysStringLen(bstr1);

	BSTR bstr = ori_str.AllocSysString();

//step 1:获取所有的chunks
	FindAllTrunks(bstr,dichashmap);
	if(ChunkList.size()>1)
	{
		//step 2:找到所有chunks里面长度最大的若干个.
		GetMaxLenChunks();
		if(ChunkList.size()>1)
		{
			//step 3:利用平均长度
			MaximumAvargeLength(ChunkList);
			if(ChunkList.size()>1)
			{
				//step 4:利用方差
				MinimumVariance(ChunkList);
				if(ChunkList.size()>1)
				{
					//step 5:利用词频		
				}
			}
		
		}
	
	}

	return TRUE;
}
自己构造的一个chunk类

class Chunk
{
public:
	Chunk();
	Chunk(const Chunk& chunk);
	~Chunk();

public:
	vector<BSTR> m_chunk;
	int m_MaxLength;
	float m_MiniVariance;
	float m_maxavarlen ;
public:
	void push_back(BSTR str);

};




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值