最大匹配分词算法

全文检索有两个重要的过程:

 1分词

  2倒排索引

我们先看分词算法

目前对中文分词有两个方向,其中一个是利用概率的思想对文章分词。 也就是如果两个字,一起出现的频率很高的话,我们可以假设这两个字是一个词。这里可以用一个公式衡量:M(A,B)=P(AB)/P(A)P(B),其中 A表示一个字,B表示一个字,P(AB)表示AB相邻出现的概率,P(A)表示A在这篇文章中的频度,P(B)表示B在这篇文章中的频度。用概率分词的好 处是不需要借助词典的帮助,坏处是算法比较麻烦,效率不高,也存在一定的出错率。

另外的一个方向是使用词典分词。就是事先为程序准备一个词典,然后通过这个词典对文章分词。目前较流行的方式有正向最大匹配算法和逆向最大匹配算法。逆向最大匹配算法在准确性上要更好一些。

以 “我是一个坏人” 为例,并最大词长为3

正向的顺序为

我是一

我是

我 ===> 得到一个词

是一个

是一

是 ===>得到一个词

一个坏

一个===> 得到一个词

坏人===>得到一个词

结果 我、是、一个、坏人

反向算法

个坏人

坏人==> 坏人

是一个

一个==> 一个

我是

是==> 是

我==> 我

结果 我、是、一个、坏人

java代码如下

package data;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 最大匹配分词算法
 *
 * @author JYC506
 *
 */
public class SplitString {

	private Set<String> set = new HashSet<String>();
	private int positiveOver = 0;
	private int reverseOver = 0;

	/**
	 * 正向最大匹配
	 *
	 * @param str 要分词的句子
	 * @param num 词的最大长度
	 * @return
	 */
	public String[] positiveSplit(String str, int maxSize) {
		int tem = 0;
		int length = str.length();
		String[] ss = new String[length];
		char[] cc = str.toCharArray();
		for (int i = 0; i < length; i++) {
			positiveOver = 0;
			String sb = this.toStr(cc, i, maxSize);
			ss[tem++] = sb;
			i = i + positiveOver;
		}
		String[] ss2 = new String[tem];
		System.arraycopy(ss, 0, ss2, 0, tem);
		return ss2;
	}

	/**
	 * 添加词库
	 *
	 * @param words
	 */
	public void addWord(String[] words) {
		for (String st : words) {
			this.set.add(st);
		}
	}

	/**
	 * 逆向最大匹配
	 *
	 * @param str
	 * @param num
	 * @return
	 */
	public String[] reverseSplit(String str, int num) {
		int tem = 0;
		int length = str.length();
		String[] ss = new String[length];
		char[] cc = str.toCharArray();
		for (int i = str.length() - 1; i > -1; i--) {
			reverseOver = 0;
			String sb = this.toStr2(cc, i, num);
			tem++;
			ss[--length] = sb;
			i = i - reverseOver;
		}
		String[] ss2 = new String[tem];
		System.arraycopy(ss, str.length() - tem, ss2, 0, tem);
		return ss2;
	}

	private String toStr(char[] cs, int start, int num) {
		int num2 = num;
		out: for (int j = 0; j < num; j++) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < num2; i++) {
				if (start + i < cs.length) {
					sb.append(cs[start + i]);
				} else {
					num2--;
					j--;
					continue out;
				}
			}
			if (set.contains(sb.toString())) {
				positiveOver = num2 - 1;
				return sb.toString();
			}
			num2--;
		}
		return String.valueOf(cs[start]);
	}

	private String toStr2(char[] cs, int start, int num) {
		int num2 = num;
		for (int j = 0; j < num; j++) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < num2; i++) {
				int index = start - num2 + i + 1;
				if (index > -1) {
					sb.append(cs[index]);
				} else {
					num2--;
				}
			}
			if (set.contains(sb.toString())) {
				reverseOver = num2 - 1;
				return sb.toString();
			}
			num2--;
		}
		return String.valueOf(cs[start]);
	}

	public static void main(String[] args) {
		String[] words = new String[] { "我们", "我们五人", "五人一组", "一组" };
		SplitString ss = new SplitString();
	    /*添加词到词库*/
		ss.addWord(words);
		String st = "我们五人一组";
		System.out.println("要分词的句子:" + st);
		/*使用两种方式分词,下面我指定最大词长度为4*/
		String[] ss2 = ss.reverseSplit(st, 4);
		String[] ss1 = ss.positiveSplit(st, 4);
		System.out.println("正向最大匹配分词算法分词结果:" + Arrays.toString(ss1));
		System.out.println("逆向最大匹配分词算法分词结果:" + Arrays.toString(ss2));
	}

}

运行结果

时间: 2024-10-12 07:08:31

最大匹配分词算法的相关文章

逆向最大匹配分词算法C#

逆向顺序 句子:大家好我叫XX我是一名程序员 程序员 -> 序员 -> 员 名程序 -> 程序 -> 序 一名程 -> 名程 -> 程 是一名 -> 一名 -> 名 我是一 -> 是一 -> 一 X我是 -> 我是 -> 是 XX我  -> X我 -> 我 叫XX  -> XX -> X 我叫X -> 叫X -> X 好我叫 -> 我叫 -> 叫 家好我 -> 好我 -> 我

双向最大匹配分词算法

#!/usr/bin/python #encoding=gbk import sys dictMaxLength = 5 dctDict = {} encoding='gbk' ''' 初始化字典.初始化最大词长 ''' def initDct(dct): global dctDict global dictMaxLength dctobj = open(dct) for line in dctobj: line = line.strip() word = line.split("\t"

NLP: 中文分词算法--正向最大匹配 Forward Maximum Matching

最近接触NLP中文分词, 在lunr.js的基础上, 实现了中文的最大正向匹配分词. 某些情况下, 我们在服务器端进行中文文本分词可以使用完整的基于mmseg算法的分词模块, 例如nodejieba, node-segment, 盘古分词等等,  但是在客户端环境下, 我们不能使用这些复杂的分词算法进行分词, 这个时候可以根据已经生成的索引进行简单的客户端分词, 就是所说的FMM (Forward Maximum Matching, 正向最大匹配), 有时候也可以使用正向匹配. 在做FMM的时候

Mmseg中文分词算法解析

@author linjiexing 开发中文搜索和中文词库语义自己主动识别的时候,我採用都是基于mmseg中文分词算法开发的Jcseg开源project.使用场景涉及搜索索引创建时的中文分词.新词发现的中文分词.语义词向量空间构建过程的中文分词和文章特征向量提取前的中文分词等,整体使用下来,感觉jcseg是一个非常优秀的开源中文分词工具,并且可配置和开源的情况下,能够满足非常多场景的中文分词逻辑.本文先把jcseg使用到最主要的mmseg算法解析一下. 1. 中文分词算法之争 在分析mmseg

浅谈分词算法(2)基于词典的分词方法

[TOC] 前言 在浅谈分词算法(1)分词中的基本问题中我们探讨了分词中的基本问题,也提到了基于词典的分词方法.基于词典的分词方法是一种比较传统的方式,这类分词方法有很多,如:正向最大匹配(forward maximum matching method, FMM).逆向最大匹配(backward maximum matching method,BMM).双向扫描法.逐词遍历法.N-最短路径方法以及基于词的n-gram语法模型的分词方法等等.对于这类方法,词典的整理选择在其中占到了很重要的作用,本

浅谈分词算法(1)分词中的基本问题

[TOC] 前言 分词或说切词是自然语言处理中一个经典且基础的问题,在平时的工作中也反复的接触到分词问题,用到了不同的模型,不同的方法应用在各个领域中,所以想对分词问题做一个系统的梳理.大多数分词问题主要是针对类似汉语.韩语.日语等,词语之间并没有天然的分割,而像英语等,句子中是带有天然的分割的.但是英语也会涉及到分词问题,比如实体识别.词性标注等内容.而本系列文章更多的是讨论汉语中的分词问题,首先我们从分词问题的基本出发,之后从传统的词典分词到将分词转为序列标注问题的分词,以及最新的结合深度学

中文分词算法综述

英文文本词与词之间以空格分隔,方便计算机识别,但是中文以字为单位,句子所有字连起来才能表达一个完整的意思.如英文"I am writing a blog",英文词与词之间有空格进行隔开,而对应的中文"我在写博客",所有的词连在一起,计算机能很容易的识别"blog"是一个单词,而很难知道"博"."客"是一个词,因此对中文文本序列进行切分的过程称为"分词".中文分词算法是自然语言处理的基础,

机器学习基础——一文讲懂中文分词算法

在前文当中,我们介绍了搜索引擎的大致原理.有错过或者不熟悉的同学,可以点击下方的链接回顾一下前文的内容. ML基础--搜索引擎基本原理 在介绍爬虫部分的时候,我们知道,爬虫在爬取到网页的内容之后,会先进行一些处理.首先要做的就是过滤掉HTML当中的各种标签信息,只保留最原生的网页内容.之后,程序会对这些文本内容提取关键词. 今天我们就来讲讲关键词提取当中最重要的一个部分--中文分词. 在世界上众多的语言当中,中文算是比较特殊的一种.许多语言自带分词信息,比如英文,机器学习写作machine le

在Hadoop上运行基于RMM中文分词算法的MapReduce程序

原文:http://xiaoxia.org/2011/12/18/map-reduce-program-of-rmm-word-count-on-hadoop/ 在Hadoop上运行基于RMM中文分词算法的MapReduce程序 23条回复 我知道这个文章标题很“学术”化,很俗,让人看起来是一篇很牛B或者很装逼的论文!其实不然,只是一份普通的实验报告,同时本文也不对RMM中文分词算法进行研究.这个实验报告是我做高性能计算课程的实验里提交的.所以,下面的内容是从我的实验报告里摘录出来的,当作是我学