关闭

编辑距离 算法详述计算两个字符串差异 c++代码

标签: c语言vc
670人阅读 评论(0) 收藏 举报
分类:

题目描述:

要求两字符串有差异的字符个数。例如: 
aaaaabaaaaa 
aaaaacaabaa 
这两个字符串,最大公共字串长度是5,但它们只有两个字符不同,函数输出值应为2。 
如果是: 
aaabbbcccddd 
aaaeeeddd 
函数的输出值应该是6。 

比较形象地形容一下,把两个字符串排成上下两行,每个字符串都可以在任何位置插入空格以便上下对齐,每个列上至少有一个字符来自这两个字符串。当对齐程度最高的时候,没有对上的列的数即为函数输出值。 
aaabbbcccddd 
aaaeeeddd 
最优对齐状态是: 
aaabbbcccddd 
aaaeee     ddd 
没有对上的列是6,函数输出值为6。 
如果是: 
abcde 
acefg 
最优对齐状态是: 
abcde 
a  c  efg 
没有对上的列数是4,函数输出值为4。

 

 

问题抽象归类:(编辑距离问题)

设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括:

(1)删除一个字符;
(2)插入一个字符;
(3)将一个字符改为另一个字符。
将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B)。试设计一个有效算法,对任给的2个字符串A和B,计算出它们的编辑距离d(A,B)。
要求:
输入:第1行是字符串A,第2行是字符串B。
输出:字符串A和B的编辑距离d(A,B)

 

 

思路:动态规划

开一个二维数组d[i][j]来记录a0-ai与b0-bj之间的编辑距离,要递推时,需要考虑对其中一个字符串的删除操作、插入操作和替换操作分别花费的开销,从中找出一个最小的开销即为所求

具体算法:

首先给定第一行和第一列,然后,每个值d[i,j]这样计算:d[i][j]   =   min(d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+(s1[i]  ==  s2[j]?0:1));   
 最后一行,最后一列的那个值就是最小编辑距离


Levenshtein Distance (编辑距离) 算法详解

编辑距离即从一个字符串变换到另一个字符串所需要的最少变化操作步骤(以字符为单位,如son到sun,s不用变,将o->s,n不用变,故操作步骤为1)。

为了得到编辑距离,我们画一张二维表来理解,以beauty和batyu为例:

 

图示如1单元格位置即是两个单词的第一个字符[b]比较得到的值,其值由它上方的值(1)、它左方的值(1)和、它左上角的值(0)来决定。当单元格所在的行和列所对应的字符(如3对应的是a和b)相等时,它左上角的值+0,否则加1(如在1处,[b]=[b]故左上角的值加0即0+0=0,而在2处[b]!=[b] 故左上角的值加1即1+1=2)。然后再将单元格的左单元格和上单元格的值分别加1,(,然后取相加后得到的三个结果的最小值作为该单元的值如1处相加后其左上、左、上的值为(0,2,2),故1单元格的值为0,而在3处,得到的值为(2,3,1),故3单元格的值为1)。

算法证明

这个算法计算的是将s[1…i]转换为t[1…j](例如将beauty转换为batyu)所需最少的操作数(也就是所谓的编辑距离),这个操作数被保存在d[i,j](d代表的就是上图所示的二维数组)中。

  • 在第一行与第一列肯定是正确的,这也很好理解,例如我们将beauty转换为空字符串,我们需要进行的操作数为beauty的长度(所进行的操作为将beauty所有的字符丢弃)。
  • 我们对字符可能进行的操作有三种:
  • 将s[1…n]转换为t[1…m]当然需要将所有的s转换为所有的t,所以,d[n,m](表格的右下角)就是我们所需的结果。
  • 如果我们可以使用k个操作数把s[1…i]转换为t[1…j-1],我们只需要把t[j]加在最后面就能将s[1…i]转换为t[1…j],操作数为k+1
  • 如果我们可以使用k个操作数把s[1…i-1]转换为t[1…j],我们只需要把s[i]从最后删除就可以完成转换,操作数为k+1
  • 如果我们可以使用k个操作数把s[1…i-1]转换为t[1…j-1],我们只需要在需要的情况下(s[i] != t[j])把s[i]替换为t[j],所需的操作数为k+cost(cost代表是否需要转换,如果s[i]==t[j],则cost为0,否则为1)。

这个证明过程只能证明我们可以得到结果,但并没有证明结果是最小的(即我们得到的是最少的转换步骤)。所以我们引进了另外一个算法,即d[i,j]保存的是上述三种操作中操作数最小的一种。这就保证了我们获得的结果是最小的操作数

 

可能进行的改进

    • 现在的算法复杂度为O(mn),可以将其改进为O(m)。因为这个算法只需要上一行和当前行被存储下来就可以了。
    • 如果需要重现转换步骤,我们可以把每一步的位置和所进行的操作保存下来,进行重现。
    • 如果我们只需要比较转换步骤是否小于一个特定常数k,那么只计算高宽宽为2k+1的矩形就可以了,这样的话,算法复杂度可简化为O(kl),l代表参加对比的最短string的长度。
    • 我们可以对三种操作(添加,删除,替换)给予不同的权值(当前算法均假设为1,我们可以设添加为1,删除为0,替换为2之类的),来细化我们的对比。
    • 如果我们将第一行的所有cell初始化为0,则此算法可以用作模糊字符查询。我们可以得到最匹配此字符串的字符串的最后一个字符的位置(index number),如果我们需要此字符串的起始位置,我们则需要存储各个操作的步骤,然后通过算法计算出字符串的起始位置。
    • 这个算法不支持并行计算,在处理超大字符串的时候会无法利用到并行计算的好处。但我们也可以并行的计算cost values(两个相同位置的字符是否相等),然后通过此算法来进行整体计算。
    • 如果只检查对角线而不是检查整行,并且使用延迟验证(lazy evaluation),此算法的时间复杂度可优化为O(m(1+d))(d代表结果)。这在两个字符串非常相似的情况下可以使对比速度速度大为增加。、




  1. #include <stdio.h>     
  2. #include <string.h>     
  3. char s1[1000],s2[1000];     
  4. int min(int a,int b,int c) {     
  5.     int t = a < b ? a : b;     
  6.     return t < c ? t : c;     
  7. }     
  8. void editDistance(int len1,int len2)  
  9. {     
  10.     int** d=new int*[len1+1];  
  11.     for(int k=0;k<=len1;k++)  
  12.         d[k]=new int[len2+1];    
  13.     int i,j;     
  14.     for(i = 0;i <= len1;i++)     
  15.         d[i][0] = i;     
  16.     for(j = 0;j <= len2;j++)     
  17.         d[0][j] = j;     
  18.     for(i = 1;i <= len1;i++)     
  19.         for(j = 1;j <= len2;j++)  
  20.         {     
  21.             int cost = s1[i] == s2[j] ? 0 : 1;     
  22.             int deletion = d[i-1][j] + 1;     
  23.             int insertion = d[i][j-1] + 1;     
  24.             int substitution = d[i-1][j-1] + cost;     
  25.             d[i][j] = min(deletion,insertion,substitution);     
  26.         }     
  27.         printf("%d\n",d[len1][len2]);   
  28.         for(int k=0;i<=len1;k++)  
  29.             delete[] d[k];  
  30.         delete[] d;  
  31. }     
  32. int main()  
  33. {     
  34.     while(scanf("%s %s",s1,s2) != EOF)     
  35.         editDistance(strlen(s1),strlen(s2));     
  36. }   


0
0
查看评论

C++实现两个字符串之间的Levenshtein Distance(编辑距离)

1.什么是Levenshtein Distance Levenshtein Distance,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。levenshtein() 函数返回两个字符串之间的...
  • shaojunbo24
  • shaojunbo24
  • 2015-08-04 11:14
  • 1839

最小编辑距离及其C++实现

一、问题介绍: 本题提出了一些关于将字符串x[1..m]转换成y[1..n]的操作。 这些操作有复制、替代、删除、插入、互换和终止。 这些操作所需的开销是不同的,但每个操作的开销都可以看是一个我们已经的常量,我们假设复制和替代这类操作的开销要比插入和删除这类操作的开销少。 我们用x[1..m...
  • hitrose27
  • hitrose27
  • 2010-09-01 08:51
  • 2097

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

字符串编辑距离是一个很经典的问题了,以前参加编程比赛、笔试面试的时候经常会碰到,今天看《编程之美》的3.3节中又遇到了该问题,又重新回顾了一边,顺便在这里总结一下。【问题描述】 给定一个源字符串和目标字符串,能够对源串进行如下操作: 1.在给定位置上插入一个字符 2.替换任意字符 ...
  • lgfun
  • lgfun
  • 2016-08-21 16:51
  • 360

编辑距离算法(Edit Distance)

写在前面的话今年是2016年的最后一天,外公,超级想你,我都没有想过你会不能继续再走到2017.我过得很好,每天都超级幸福,我现在在学校有一堆好朋友。哈哈,我总是能处在宇宙中心的那种人,没办法,您这么优秀才能教出这么好的孙女,好吧。我会好好学习的,我是第一女王嘛,永远都会是的。是吧,要做就做最好,要...
  • Grace_0642
  • Grace_0642
  • 2016-12-31 21:31
  • 7027

两个字符串的编辑距离-动态规划方法

概念 字符串的编辑距离,又称为Levenshtein距离,由俄罗斯的数学家Vladimir Levenshtein在1965年提出。是指利用字符操作,把字符串A转换成字符串B所需要的最少操作数。其中,字符操作包括: 删除一个字符     a) Insert a ...
  • ac540101928
  • ac540101928
  • 2016-10-11 11:51
  • 8190

两个字符串的最小编辑距离 Edit Distance

问题:Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) You h...
  • luckyjoy521
  • luckyjoy521
  • 2014-03-05 14:40
  • 3775

编辑距离 算法详述计算两个字符串差异 c++代码

题目描述: 要求两字符串有差异的字符个数。例如:  aaaaabaaaaa  aaaaacaabaa  这两个字符串,最大公共字串长度是5,但它们只有两个字符不同,函数输出值应为2。  如果是:  aaabbbcccddd ...
  • qq_30636613
  • qq_30636613
  • 2016-08-31 10:30
  • 670

【动态规划】字符串编辑距离(Levenshtein距离)算法

基本介绍Levenshtein距离是一种计算两个字符串间的差异程度的字符串度量(string metric)。我们可以认为Levenshtein距离就是从一个字符串修改到另一个字符串时,其中编辑单个字符(比如修改、插入、删除)所需要的最少次数。俄罗斯科学家Vladimir Levenshtein于1...
  • jmsyzsfq
  • jmsyzsfq
  • 2017-10-27 20:51
  • 727

求两个字符串的最短编辑距离

1.理解最小编辑距离的概念;       编辑距离是一种字符串之间相似程度的计算方法。按照Damerau给出的定义,即两个字符串之间的编辑距离等于使一个字符串变成另外一个字符串而进行如下操作的最少次数。用edit来表示编辑距离。共四种操作,分别是:...
  • u010189459
  • u010189459
  • 2014-06-05 18:27
  • 2030

Python实现求两个字符串的最短编辑距离

前几天用C++实现了秋来你哥哥
  • u010189459
  • u010189459
  • 2014-06-10 21:31
  • 1303
    个人资料
    • 访问:5961次
    • 积分:114
    • 等级:
    • 排名:千里之外
    • 原创:2篇
    • 转载:24篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论