分词算法-正向最大匹配算法与逆向最大匹配算法

这两种分词方法都是机械分词方法,按照一定的策略将待分析的汉字串与机器词典中的词条进行匹配,若在词典中找到某个字符串,则匹配成功。按照扫描方向的不同,串匹配分词方法可以分为正向匹配和逆向匹配。按照不同长度优先匹配的情况,可以分为最大匹配和最小匹配。由于汉语单字成词的特点,正向最小匹配和逆向最小匹配一般很少用。一般说来,逆向匹配的切分精度略高于正向匹配,遇到的歧义现象也较少。统计结果表明,单纯使用正向最大匹配的错误率为1/169,单纯使用逆向最大匹配的错误率为1/245。但这种精度还远远不能满足实际的需要。实际使用的分词系统,都是把机械分词作为一种初分手段,还需通过利用各种其它的语言信息来进一步提高切分的准确率。

例:今天来了许多新同事

1.正向最大匹配算法,规定最大匹配长度为5

今天来了许

今天来了

今天来

今天====》得到一个词–今天

来了许多新

来了许多

来了许

来了

来====》得到一个词–来

了许多新同

了许多新

了许多

了许

了====》得到一个词–了

许多新同事

许多新同

许多新

许多====》得到一个词–许多

新同事

新同

新====》得到一个词–新

同事====》得到一个词–同事

最后正向最大匹配的结果是:/今天/来/了/许多/新/同事/

2.逆向最大匹配算法,规定最大匹配长度为5

许多新同事

多新同事

新同事

同事====》得到一个词–同事

来了许多新

了许多新

许多新

多新

新====》得到一个词–新

天来了许多

来了许多

了许多

许多====》得到一个词–许多

今天来了

天来了

来了

了====》得到一个词–了

今天来

天来

来====》得到一个词–来

今天====》得到一个词–今天

最后反向最大匹配的结果是: /今天/来/了/许多/新/同事/

正向最大匹配和反向最大匹配的结果并不一定相同。我一个人吃饭这句话, 按照上述正向最大匹配的结果是:/我/一个/人/吃饭/;按照上述逆向最大匹配的结果是:/我/一/个人/吃饭/。这次两种方式的结果就不一致了。

借助于C++STL的map和BM算法的思想,我简单实现了这两种算法。

#include<map>
#include<string>
#include<iomanip>
#include<iostream>
using namespace std;

int main()
{
    string str;
    map<int,string> dict;
    int maxlength=0,temp=0,i,j,size;
    cin>>size;
	for(i=0;i<size;i++)
    {
  		temp=0;
 		cin>>str;
 		if(str.length()>maxlength) maxlength=str.length();
 		//记录词典中字符串的最大长度
		for(j=0;j<str.length();j++)
		{
			temp+=str[j];
			temp=temp*10;
		}
		dict[temp]=str;
		//制作key-value键值对
    }
    i=0,j=0;
	cin>>str;
	int pos=-1;
	map<int,string>::iterator map_it;
	//从前向后匹配
	while(i<str.length())
	{
		temp=0;
		for(j=i;j<str.length();j++)
		{
			temp+=str[j];
			temp=temp*10;
			map_it=dict.find(temp);
			if(map_it!=dict.end()) pos=j;
			//如果匹配成功记录匹配的位置
			if(map_it!=dict.end()&&j==str.length()-1)
			{
				cout<<str.substr(i,j)<<endl;
				i=str.length();
				break;
			}
		 	//如果已经到末尾了就不需要记录位置直接输出即可
			if(map_it==dict.end()&&(j-i>=maxlength-1||j==str.length()-1))
			{
				if(pos==-1)
				//如果没有匹配成功进行单字切分向后移动一个字继续匹配
				{
					cout<<str.substr(i,2)<<endl;
					i+=2;
					break;
				}
				else
				//如果匹配成功输出并移动到匹配成功后的下一个位置继续匹配
				{
					cout<<str.substr(i,pos-i+1)<<endl;
					i=pos+1;
					pos=-1;
					break;
				}
			}
		}
	}
}
#include<map>
#include<string>
#include<iomanip>
#include<iostream>
using namespace std;  

int main()
{
    string str;
    map<int,string> dict;
    int maxlength=0,temp=0,i,j,size;
    cin>>size;
    for(i=0;i<size;i++)
    {
        temp=0;
        cin>>str;
        if(str.length()>maxlength) maxlength=str.length();
        //记录词典中字符串的最大长度
        for(j=str.length()-1;j>=0;j--)
        {
            temp+=str[j];
            temp=temp*10;
        }
        dict[temp]=str;
		//制作key-value键值对
    }
    cin>>str;
    int pos=-1;
    i=j=str.length()-1;
    map<int,string>::iterator map_it;
    //从后向前匹配
    while(i>=0)
    {
        temp=0;
        for(j=i;j>=0;j--)
        {
            temp+=str[j];
            temp=temp*10;
            map_it=dict.find(temp);
            if(map_it!=dict.end()) pos=j;
            //如果匹配成功记录匹配的位置
            if(map_it!=dict.end()&&j==0)
            {
                cout<<str.substr(0,i-j+1)<<endl;
                i=-1;
                break;
            }
            //如果已经到末尾了就不需要记录位置直接输出即可
            if(map_it==dict.end()&&(i-j>=maxlength-1||j==0))
            {
            	if(pos==-1)
				//如果没有匹配成功进行单字切分向后移动一个字继续匹配
				{
					cout<<str.substr(i-1,2)<<endl;
					i-=2;
					break;
				}
				else
				//如果匹配成功输出并移动到匹配成功后的下一个位置继续匹配
				{
                	cout<<str.substr(pos,i-pos+1)<<endl;
                	i=pos-1;
                	pos=-1;
                	break;
				}
            }
        }
    }
}
时间: 2024-10-11 02:53:43

分词算法-正向最大匹配算法与逆向最大匹配算法的相关文章

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

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

【nlp】正向最大匹配算法、逆向最大匹配算法、双向最大匹配算法代码实现

from collections import defaultdict ''' 最大匹配算法 Maximum Match { 正向最大匹配, 逆向最大匹配, 双向最大匹配; 分词算法设计中的几个基本原则: 1.颗粒度越大越好:用于进行语义分析的文本分词,要求分词结果的颗粒度越大, 即单词的字数越多,所能表示的含义越确切,如:“公安局长”可以分为“公安 局长”.“公安局 长”.“公安局长” 都算对,但是要用于语义分析,则“公安局长”的分词结果最好(当然前提是所使用的词典中有这个词) 2.切分结果中

最大匹配分词算法

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

中文分词算法综述

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

中文分词常用算法之基于词典的逆向最大匹配

算法描述: S1为带切分字符串,S2为空,MaxLen为词典中的最大词长 判断S1是否为空,若是则输出S2 从S1右边开始,取出待处理字符串str(其中str的长度小于MaxLen) 查看str是否在词典中,若是则转5,若否则转6 S2+=str+”/”,S1-=str,转2 将str最左边的一个字去掉 判断str是否为单字,若是则转5,若否则转4 Java实现代码: 1 public static List<String> BMM(String text) { 2 Stack<Stri

。一个最大逆向匹配分词算法的例子

原文链接地址:http://www.52nlp.cn/maximum-matching-method-of-chinese-word-segmentation/ 逆向匹配法思想与正向一样,只是从右向左切分,这里举一个例子: 输入例句:S1=”计算语言学课程有意思” : 定义:最大词长MaxLen = 5:S2= ” “:分隔符 = “/”: 假设存在词表:…,计算语言学,课程,意思,…: 最大逆向匹配分词算法过程如下: (1)S2=””:S1不为空,从S1右边取出候选子串W=”课程有意思”: (

自然语言处理 最大逆向匹配分词算法

输入例句:S1="计算语言学课程有意思" : 定义:最大词长MaxLen = 5:S2= " ":分隔符 = “/”: 假设存在词表:…,计算语言学,课程,意思,…: 最大逆向匹配分词算法过程如下: (1)S2="":S1不为空,从S1右边取出候选子串W="课程有意思": (2)查词表,W不在词表中,将W最左边一个字去掉,得到W="程有意思": (3)查词表,W不在词表中,将W最左边一个字去掉,得到W=&q

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

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

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

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