码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-05-12 15:21:01      阅读:864      评论:0      收藏:0      [点我收藏+]

标签:

这两种分词方法都是机械分词方法,按照一定的策略将待分析的汉字串与机器词典中的词条进行匹配,若在词典中找到某个字符串,则匹配成功。按照扫描方向的不同,串匹配分词方法可以分为正向匹配和逆向匹配。按照不同长度优先匹配的情况,可以分为最大匹配和最小匹配。由于汉语单字成词的特点,正向最小匹配和逆向最小匹配一般很少用。一般说来,逆向匹配的切分精度略高于正向匹配,遇到的歧义现象也较少。统计结果表明,单纯使用正向最大匹配的错误率为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;  
				}
            }  
        }  
    }  
}




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

标签:

原文地址:http://blog.csdn.net/qq_32400847/article/details/51361664

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!