问题

字符串的编辑距离也被称为距Levenshtein距离(Levenshtein Distance),属于经典算法,常用方法使用递归,更好的方法是使用动态规划算法,以避免出现重叠子问题的反复计算,减少系统开销。


思考

也许我们以前遇过这样一个问题:

计算两个字符串的相似度。

关于相似度的定义,从下面这个例子了解一下:

比如,对于”abcdefg”和”abcdef”两个字符串来说,我们认为可以通过增加/减少一个”g”的方式来达到目的。把这个操作所需要的次数定义为两个字符串的距离,而相似度等于”距离+1”的倒数。也就是说,”abcdefg”和”abcdef”的距离为1,相似度 为1/2=0.5。给定任意两个字符串,你是否能写出一个算法来计算它们的相似度呢?(其实这个问题的关键是要求两个字符串的编辑距离。)

这个问题其实是由俄罗斯科学家Vladimir Levenshtein在1965年提出的。


分析

*先考虑一些特殊情况:

d(null, B) = strlen(B);
d(A, null) = strlen(A);
d(A, B) = 0 当且仅当 A = B.

*再考虑一般情况下的 d(A, B)

运用动态规划求出递归方程,将原问题分解为若干个子问题进行求最优解,而后得出原问题的最优解,采用“填表的方法”。
设计步骤:对每个子问题只求解一次,将其结果保存在一张表(构造一个行数为n+1 列数为 m+1 的矩阵 , 用来保存完成某个转换需要执行的最少操作的次数, 其中,n为字符串A的长度,m为字符串B的长度)中。

对矩阵中的一点d[i][j],保存从A[0:i]变到B[0:j]的编辑距离。其中,这里S[0:i]变到t[0:j]有三种情况,求得这三种情况的最小值作为最小操作数:

(1)设可以在k1个操作内将s[0:i-1]转换为t[0:j],用k1+1次操作将s[0:i]转化为t[0:j],只需要先在“s[0:i]转化为t[0:j]”的操作开端做1次移除操作移除s[i]将s[0:i]转化为s[0:i-1],然后再做k1个操作就可以转换为t[0:j]。对应表格,对应矩阵d[i][j]处即填入k1+1。(左)


(2)设可以在k2个操作内将s[0:i]转换为t[0:j-1],用k2+1次操作将s[0:i]转化为t[0:j],先用k2次操作将s[0:i]转化为t[0:j-1],然后再执行1次插入操作在“s[0:i]变成t[0:j-1]的操作”的末尾插入“增加t[j]”的一次操作,即可将s[0:i]转化为t[0:j]。对应矩阵d[i][j]处即填入k2+1。(上)


(3)设可以在k3个操作内将s[0:i-1]转化为t[0:j-1] ,此时需分情况讨论:
**若s[i]==t[j],S[0:i]变到t[0:j]就只要k3个操作,对应矩阵d[i][j]处即填入k3;
**若s[i]!=t[j],则需1次换操作加在s[0:i-1]转化为t[0:j-1]的操作数基础上就可以将S[0:i]变到t[0:j],共k3+1次。对应矩阵d[i][j]处即填入k3+1。(左上角)

其实,通过上面三种情况的分析,我们可以得到下面这个递推公式:


实现过程

下面我们用一个简单的例子来实现下算法的过程,以abc和abe这两个字符串为例

  1. 首先进行如下初始化(开辟d[n+1][m+1]数据空间,相应位置数据初始化):

    (ps:”A处”是一个标记,只是为了方便讲解,不是这个表的内容。)

  2. 计算A处的值

    它的值取决于:左边的1、上边的1、左上角的0.
    按照上面我们的分析:
    上面的值和左面的值都要求加1,这样得到1+1=2。
    A处 由于是两个a相同,左上角的值加0.这样得到0+0=0。
    这是后有三个值,左边的计算后为2,上边的计算后为2,左上角的计算为0,所以A处 取他们里面最小的0.

  3. 于是表成为下面的样子

    在B处 会同样得到三个值,左边计算后为3,上边计算后为1,在B处 由于对应的字符为a、b,不相等,所以左上角应该在当前值的基础上加1,这样得到1+1=2,在(3,1,2)中选出最小的为B处的值。

  4. 于是表就更新了

    C处 计算后:上面的值为2,左边的值为4,左上角的:a和e不相同,所以加1,即2+1,左上角的为3。在(2,4,3)中取最小的为C处 的值。

  5. 依次推得到

    I处: 表示abc 和abe 有1个需要编辑的操作。这个是需要计算出来的。
    同时,也获得一些额外的信息。
    A处: 表示a 和a 需要有0个操作。字符串一样
    B处: 表示ab 和a 需要有1个操作。
    C处: 表示abe 和a 需要有2个操作。
    D处: 表示a 和ab 需要有1个操作。
    E处: 表示ab 和ab 需要有0个操作。字符串一样
    F处: 表示abe 和ab 需要有1个操作。
    G处: 表示a 和abc 需要有2个操作。
    H处: 表示ab 和abc 需要有1个操作。
    I处: 表示abe 和abc 需要有1个操作。


程序实现

#include<bits/stdc++.h>
using namespace std; int min(int a,int b,int c)
{
return (a<b)?(a<c?a:c):(b<c?b:c);
}
int main()
{
FILE * file;
freopen("input.txt", "r", stdin);
freopen("output.txt","w",stdout); int d[6][8];
string a,b;
cin>>a>>b; for (int i=0;i<=b.size()+1;i++)
{
for (int j=0; j<=a.size()+1;j++)
{
if (i==0&&j==0)
d[i][j]=0;
else if (i==0&& j > 0)
d[i][j]=j;
else if (i>0&&j==0)
d[i][j]=i; else if(i>=1&&j>=1)
{
int k =((b[i-1]==a[j-1])?0:1);
d[i][j]=min(d[i-1][j]+1, d[i][j-1]+1,d[i-1][j-1]+k);
}
}
}
/*
for(int i=0;i<b.size()+1;i++)
{
for(int j=0;j<a.size()+1;j++)
{
cout<<d[i][j]+" ";
}
cout<<endl;
}
*/
cout<<d[b.size()+1][a.size()+1];
return 0;
}

更多

https://my.oschina.net/mustang/blog/58125
https://blog.csdn.net/the_k1/article/details/78442814
https://www.cnblogs.com/cangT-Tlan/p/6219005.html
http://www.cnblogs.com/jiabei521/p/3353390.html
http://wdhdmx.iteye.com/blog/1343856

【附:一文一图】

动态规划 001 - 编辑距离(Levenshtein Distance)问题的更多相关文章

  1. 字符串相似度算法(编辑距离Levenshtein Distance)的应用场景

    应用场景 DNA分析: 将DNA的一级序列如β-球蛋白基因的第一个外显子(Exon)转化为分子“结构图”,然后由所得“结构图”提取图的不变量,如分子连接性指数.以图的不变量作为自变量,再由相似度计算公 ...

  2. C#实现Levenshtein distance最小编辑距离算法

    Levenshtein distance,中文名为最小编辑距离,其目的是找出两个字符串之间需要改动多少个字符后变成一致.该算法使用了动态规划的算法策略,该问题具备最优子结构,最小编辑距离包含子最小编辑 ...

  3. Levenshtein Distance算法(编辑距离算法)

    编辑距离 编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符, ...

  4. 扒一扒编辑距离(Levenshtein Distance)算法

    最近由于工作需要,接触了编辑距离(Levenshtein Distance)算法.赶脚很有意思.最初百度了一些文章,但讲的都不是很好,读起来感觉似懂非懂.最后还是用google找到了一些资料才慢慢理解 ...

  5. 用C#实现字符串相似度算法(编辑距离算法 Levenshtein Distance)

    在搞验证码识别的时候需要比较字符代码的相似度用到"编辑距离算法",关于原理和C#实现做个记录. 据百度百科介绍: 编辑距离,又称Levenshtein距离(也叫做Edit Dist ...

  6. [转]字符串相似度算法(编辑距离算法 Levenshtein Distance)

    转自:http://www.sigvc.org/bbs/forum.php?mod=viewthread&tid=981 http://www.cnblogs.com/ivanyb/archi ...

  7. Levenshtein Distance(编辑距离)算法与使用场景

    前提 已经很久没深入研究过算法相关的东西,毕竟日常少用,就算死记硬背也是没有实施场景导致容易淡忘.最近在做一个脱敏数据和明文数据匹配的需求的时候,用到了一个算法叫Levenshtein Distanc ...

  8. 利用Levenshtein Distance (编辑距离)实现文档相似度计算

    1.首先将word文档解压缩为zip /** * 修改后缀名 */ public static String reName(String path){ File file=new File(path) ...

  9. 字符串相似度算法(编辑距离算法 Levenshtein Distance)(转)

    在搞验证码识别的时候需要比较字符代码的相似度用到“编辑距离算法”,关于原理和C#实现做个记录. 据百度百科介绍: 编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个 ...

随机推荐

  1. SSH非交互式密码授权远程执行脚本

    公司有上百台服务器,需要为每台服务器都执行一个脚本,因为所有服务器的账号密码都是一样的,所以可以不用搭建ansible等自动化运维工具,我们直接通过SSH远程执行即可完成. 本文以三台服务器为例,系统 ...

  2. protobuf-net与FlatBuffers

    protobuf-net Protobuf是google开源的一个项目,用户数据序列化反序列化,google声称google的数据通信都是用该序列化方法.它比xml格式要少的多,甚至比二进制数据格式也 ...

  3. Python全栈工程师(列表、拷贝)

    ParisGabriel     感谢 大家的支持  你们的阅读评价就是我最好的更新动力  我会坚持吧排版做的越来越好      每天坚持 一天一篇 点个订阅吧  灰常感谢    当个死粉也阔以 Py ...

  4. vim使用的一些积累

    vi visual interfacevim vi improved vim模式:编辑模式(命令模式)输入模式末行模式 编辑模式下,zz保存并退出移动光标:(编辑模式)1.逐字符移动 h 左 l 右 ...

  5. ASP.NET 抓取网页内容

    (转)ASP.NET 抓取网页内容 ASP.NET 抓取网页内容-文字 ASP.NET 中抓取网页内容是非常方便的,而其中更是解决了 ASP 中困扰我们的编码问题. 需要三个类:WebRequest. ...

  6. android 继承ListView实现滑动删除功能.

    在一些用户体验较好的应用上,可以经常遇见   在ListView中  向左或向右滑动便可删除那一项列表. 具体实现  则是继承ListView实现特定功能即可. (1). 新建 delete_butt ...

  7. 【转】Itween 贝塞尔曲线(一)

    原地址:点击打开链接 1.回调函数 回调函数,即当动画完成时那瞬间需要执行一次的一个函数,it中默认有一个onComplete函数,当动画完成时会自动执行,且你可以提供需要传递的一些参数.见如下代码: ...

  8. Mifare简介

    Mifare简介 MIFARE是NXP的知名品牌,是一个应用广泛的非接触式IC产品(13.56MHz非接触性辨识技术),一个典型的通信距离为10厘米,在全球有40多个不同的应用领域.有2.6亿个读写器 ...

  9. RabbitMQ磁盘警报

    RabbitMQ磁盘警报 当可用磁盘空间低于配置的限制(默认为50MB)时,将触发警报,所有生产者将被阻止.目标是避免填满整个磁盘,这将导致节点上的所有写操作失败,并可能导致RabbitMQ终止.为了 ...

  10. 【bzoj4154】[Ipsc2015]Generating Synergy KD-tree

    题目描述 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 输入 第一行一个数T,表示数据组数 接下来每组数据的第一行三个数n,c,q表示结 ...