之所以研究这个算法,是因为最近在研究NLP中文的分词,所谓分词就是将一个完整的句子,例如“计算语言学课程有意思”,分解成一些词组单元“计算语言学,课程,有,意思”。 “最大匹配法” 在中文分词中有所应用,因此这里介绍一下。

  “最大匹配法” 分为正向匹配和逆向匹配,这里先看正向匹配。

  算法思想

  正向最大匹配算法:从左到右将待分词文本中的几个连续字符与词表匹配,如果匹配上,则切分出一个词。但这里有一个问题:要做到最大匹配,并不是第一次匹配到就可以切分的 。我们来举个例子:

    待分词文本: sentence[]={"计","算","语","言","学","课","程","有","意","思"}

    词表: dict[]={"计算", "计算语言学", "课程", "有", "意思"}  (真实的词表中会有成千上万个已经平时我们使用的分好的词语)  

  (1) 从sentence[1]开始,当扫描到sentence[2]的时候,发现"计算"已经在词表dict[]中了。但还不能切分出来,因为我们不知道后面的词语能不能组成更长的词(最大匹配)。

  (2) 继续扫描content[3],发现"计算语"并不是dict[]中的词。但是我们还不能确定是否前面找到的"计算语"已经是最大的词了。因为"计算语"是dict[2]的前缀。

  (3) 扫描content[4],发现"计算语言"并不是dict[]中的词。但是是dict[2]的前缀。继续扫描:

  (3) 扫描content[5],发现"计算语言学"是dict[]中的词。继续扫描下去:

  (4) 当扫描content[6]的时候,发现"计算语言学课"并不是词表中的词,也不是词的前缀。因此可以切分出前面最大的词——"计算语言学"。

  由此可见,最大匹配出的词必须保证下一个扫描不是词表中的词或词的前缀才可以结束。

  代码实现

  这里字典就临时这样简单写死,真实的情况需要构造一个hash,这样效率较高,我们看下算法的代码吧:

#include<iostream>
#include<string>
using namespace std; // 宏,计算数组个数
#define GET_ARRAY_LEN(array,len){len=(sizeof(array)/sizeof(array[0]));} string dict[] = {"计算", "计算语言学", "课程", "有", "意思"}; // 是否为词表中的词或者是词表中词的前缀
bool inDict(string str)
{
bool res = false;
int i;
int len = ; GET_ARRAY_LEN(dict, len); for (i = ; i<len; i++)
{
// 是否和词表词相等或者是词表词前缀
if( str == dict[i].substr(, str.length()))
{
res = true;
}
}
return res;
} int main()
{
string sentence = "计算语言学课程有意思";
string word = "一";
int wordlen = word.length(); int i;
string s1 = ""; for (i = ; i<sentence.length(); i = i+wordlen)
{
string tmp = s1 + sentence.substr(i, wordlen); if(inDict(tmp))
{
s1 = s1 + sentence.substr(i, wordlen);
}
else
{
cout<<"分词结果:"<<s1<<endl;
s1 = sentence.substr(i, wordlen);
}
}
cout<<"分词结果:"<<s1<<endl;
}

  我在linux下运行的结果是:

  

  可以看到分词的结果符合我们的预期,如果词表足够大,那么所有的句子都可以被分词。iao

  接下来说下逆向的最大匹配算法。

  算法思想

  逆向匹配算法大致思路是从右往左开始切分。我们还是用上面的例子:

    待分词句子: sentence[]={"计算语言学课程有意思"}

    词表: dict[]={"计算", "计算语言学", "课程", "有", "意思"}   

  首先我们定义一个最大分割长度5,从右往左开始分割:

  (1) 首先取出来的候选词W是 “课程有意思”。

  (2) 查词表,W不在词表中,将W最左边的第一个字去掉,得到W“程有意思”;

  (3) 查词表,W也不在词表中,将W最左边的第一个字去掉,得到W“有意思”;

  (4) 查词表,W也不在词表中,将W最左边的第一个字再去掉,得到W“意思”;

  (5) 查词表,W在词表中,就将W从整个句子中拆分出来,此时原句子为“计算语言学课程有”

  (6) 根据分割长度5,截取句子内容,得到候选句W是“语言学课程有”;

  (7) 查词表,W不在词表中,将W最左边的第一个字去掉,得到W“言学课程有”;

  (8) 查词表,W也不在词表中,将W最左边的第一个字去掉,得到W“学课程有”;

  (9) 依次类推,直到W为“有”一个词的时候,这时候将W从整个句子中拆分出来,此时句子为“计算语言学课程”

  (10) 根据分割长度5,截取句子内容,得到候选句W是“算语言学课程”;

  (11) 查词表,W不在词表中,将W最左边的第一个字去掉,得到W“语言学课程”;

  (12) 依次类推,直到W为“课程”的时候,这时候将W从整个句子中拆分出来,此时句子为“计算语言学”

  (13) 根据分割长度5,截取句子内容,得到候选句W是“计算语言学”;

  (14)  查词表,W在词表,分割结束。

  

  代码实现

#include<iostream>
#include<string>
using namespace std; // 宏,计算数组个数
#define GET_ARRAY_LEN(array,len){len=(sizeof(array)/sizeof(array[0]));} // 定义最大词长
#define MAX_WORD_LENGTH 5 string dict[] = {"计算", "计算语言学", "课程", "意思"}; // 是否为词表中的词
bool inDict(string str)
{
bool res = false;
int i;
int len = ; GET_ARRAY_LEN(dict, len); for (i = ; i<len; i++)
{
if( str == dict[i])
{
res = true;
}
}
return res;
} int main()
{
string sentence = "计算语言学课程有意思";
string word = "一";
int wordlen = word.length(); int i; for (i = ; i<sentence.length(); )
{
int dealstrbegin = sentence.length()-wordlen*MAX_WORD_LENGTH-i;
int dealstrlen = wordlen*MAX_WORD_LENGTH;
// 截取的要处理的字符串
string dealstr = sentence.substr(dealstrbegin, dealstrlen); int j;
for (j = ; j<MAX_WORD_LENGTH; j++)
{
int fb = j*wordlen;
int fl = wordlen*(MAX_WORD_LENGTH-j);
// 去掉签名的j个字
string tmp = dealstr.substr(fb, fl); if(inDict(tmp) || j==MAX_WORD_LENGTH- )
{
cout<<"分词结果:"<<tmp<<endl;
i=i+fl;
break;
}
}
}
}

  代码运行的结果是:

  

最大匹配算法 (Maximum Matching)的更多相关文章

  1. [Codeforces Round #508 (Div. 2)][Codeforces 1038E. Maximum Matching]

    前几天给舍友讲这题的时候感觉挺有意思的,就贴上来吧... 题目链接:1038E - Maximum Matching 题目大意:有\(n\)个棒子,每个条两端有颜色\(c1,c2\)以及他的价值\(v ...

  2. Codeforces 1038 E - Maximum Matching

    E - Maximum Matching 思路: 欧拉图 定理:一个度数为奇数的点的个数小于等于2的联通图存在欧拉回路 对于这道题目的图,点的个数为4,所以最坏的情况下4个点的度数都为奇数,在这种情况 ...

  3. Codeforces Round #508 (Div. 2) E. Maximum Matching(欧拉路径)

     E. Maximum Matching 题目链接:https://codeforces.com/contest/1038/problem/E 题意: 给出n个项链,每条项链左边和右边都有一种颜色(范 ...

  4. [codeforces 508E]Maximum Matching

    题目:Maximum Matching 传送门:http://codeforces.com/contest/1038/problem/E 分析: 一个块拥有{color1,val,color2},两个 ...

  5. SPOJ4206Fast Maximum Matching(hopcroft-karp)

    题目请戳这里 题目大意:裸的二分匹配. 题目分析:数据比较强,用来测模版的.这题用hungry跑着会比较吃力,所以用hopcroft-karp算法.这个算法较hungry高效是因为每次bfs找到一个增 ...

  6. SPOJ 4206 Fast Maximum Matching (二分图最大匹配 Hopcroft-Carp 算法 模板)

    题目大意: 有n1头公牛和n2头母牛,给出公母之间的m对配对关系,求最大匹配数.数据范围:  1 <= n1, n2 <= 50000, m <= 150000 算法讨论: 第一反应 ...

  7. CF1038E Maximum Matching 搜索/区间DP

    题目传送门:http://codeforces.com/problemset/problem/1038/E 题意:给出$N$个方块,每个方块有左右两种颜色$a,b$(可以翻转使左右两种颜色交换)和一个 ...

  8. CF#508 1038E Maximum Matching

    ---题面--- 题解: 感觉还是比较妙的,复杂度看上去很高(其实也很高),但是因为n只有100,所以还是可以过的. 考虑一个很暴力的状态f[i][j][x][y]表示考虑取区间i ~ j的方格,左右 ...

  9. Codeforces 1038E Maximum Matching

    可能写了个假算法 假设定义:含有一个欧拉路的图为类欧拉图 欧拉路的定义:一个无向连通图中,存在一条路径对所有边都遍历且仅遍历一次:判断方法:该连通图中度为奇数的点的个数不能超过2,即为0或者2 题目解 ...

随机推荐

  1. Mysql 数据类型及选择原则

    MySQL中的数据类型大的方面来分,可以分为:日期和时间.数值,以及字符串.下面就分开来进行总结. 数据库类型的选择对数据库的性能影响很大 1 . 数据类型会影响存储空间的开销 2 . 数据类型会影响 ...

  2. 对于近阶段公司代码 review 小结

    来新公司,给公司的SDK review了一下.发现了不少小问题,在此总结一下. (我下面说明问题可能是很简单,但是搞清楚某些问题还是花了些时间的,大家引以为戒吧) 先谈谈处理的问题: 1.某天QA说有 ...

  3. “使用驱动器中J:的光盘之前需要将其格式化

    不知道神马原因致使U盘无法打开——大家千万注意:以后遇见这种情况千万别格式化(当然如果你的U盘或者硬盘里没有重要东西那就另当别论),进入“开始-cmd”,因为我的U盘在电脑上读出来是J盘,所以在cmd ...

  4. saltstack常用模块

    介绍一些常用的saltstack模块,更多模块参考官方网站 1.跟安装包相关的模块:salt.states.pkg salt.states.pkg.downloaded(name, version=N ...

  5. http://www.jb51.net/article/28619.htm

    http://www.jb51.net/article/28619.htm js autocomplete 自动完成

  6. Java 线程池Future和FutureTask

    Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务. Future接口源码: public interface Future<V> ...

  7. Tensorflow平台快速搭建:Windows 7+TensorFlow 0.12.0

    Tensorflow平台快速搭建:Windows 7+TensorFlow 0.12.0 1.TensorFlow 0.12.0下载 2016年11月29日,距离TensorFlow 宣布开源刚刚过去 ...

  8. linux安装coreseek

    coreseek就是一个中文词库加上sphinx组合而成的. 1.下载coreseek 下载到/usr/local/src目录文件下 wget  http://www.coreseek.cn/uplo ...

  9. Flink快速入门

    文章目录 1 安装:下载并启动 1.1 下载 1.2 启动一个local模式的Flink集群 2 运行例子 3 集群模式安装 4 Flink on YARN 安装:下载并启动 Flink可以在Linu ...

  10. 【边框回归】边框回归(Bounding Box Regression)详解(转)

    转自:打开链接 Bounding-Box regression 最近一直看检测有关的Paper, 从rcnn, fast rcnn, faster rcnn, yolo, r-fcn, ssd,到今年 ...