正向最大匹配

按照网上资料,中文分词算法可分为三大类:基于字典、词库匹配的分词方法;基于词频度统计的分词方法和基于知识理解的分词方法。基于词库的方法,有几个问题要解决,一是词库和数据结构,二是字符串在词库的匹配方式,三是多种满足匹配的选择。正向最大匹配是基于词库的分词方法,基本思想是按照文字的正方向,与词库中的词作比对,如果多个词匹配,则取最长的词。有正向,就有逆向,就是反方向读取语句中的字去比对,据统计,准确率比正向的高。正向最大匹配就拿mmseg4j的代码学习下。找到的mmseg4j版本是1.9.1。

首先,类MMSeg使用PushbackReader将字符一个一个按顺序读取,判断字符的类型,将字符保存到一个StringBuilder中,直到遇到不符规则的字符,将该字符推回到输入流的前端。如果输入中有中文字符(其他的日文之类的这里就不管了),则对中文字符子串进行分词处理。里面有3种分词方式,先看下SimpleSeg。

	while(read && (data=readNext()) != -1) {
	<span style="white-space:pre">	</span>read = false;	//遇到同类字符zhiwei
		int type = Character.getType(data);
		String wordType = Word.TYPE_WORD;
		switch(type) {
<span style="white-space:pre">			</span>……<span style="white-space:pre">	</span>//判断字符类型,分别做不同的处理。里面还会读取字符,直到遇到不符规则的字符
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
SimpleSeg就是寻找在词库中最长的匹配。

	public Chunk seg(Sentence sen) {
		Chunk chunk = new Chunk();
		char[] chs = sen.getText();
		for(int k=0; k<3&&!sen.isFinish(); k++) {
			int offset = sen.getOffset();
			int maxLen = 0;

			//有了 key tree 的支持可以从头开始 max match
			maxLen = dic.maxMatch(chs, offset);
			
			chunk.words[k] = new Word(chs, sen.getStartOffset(), offset, maxLen+1);

			offset += maxLen + 1;
			sen.setOffset(offset);
		}
		
		return chunk;
	}
在遇到叶子节点或匹配不下去时,就是最长的匹配。

	public ArrayList<Integer> maxMatch(ArrayList<Integer> tailLens, char[] sen, int offset) {
		TreeNode node = head;
		for(int i=offset; i<sen.length; i++) {
			node = node.subNode(sen[i]);
			if(node != null) {
				if(node.isAlsoLeaf()) {
					tailLens.add(i-offset+1); 
				}
			} else {
				break;
			}
		}
		return tailLens;
	}

ComplexSeg与SimpleSeg相比,每次匹配时,有两种切分的情况,第一种是从词库找到最大匹配的词,第二种将剩下的待切分的字符串的第一个字作为单字词。两种切出一个新词后,将剩余字符串继续切分,直到产生了三个词后终止循环,根据规则选择最合适的分词。如果3次切分每次都能在词库找到长度大于1的词,就产生6种切分方式。分词规则可以看看这里 MMSEG的歧义规则

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值