【问题描述】

设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。 将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。 对于给定的字符串A和字符串B,计算其编辑距离 d(A,B)。

【算法描述】

A.问题分析三步曲

1). 子问题含义 d[i][j];//d[i][j]表示A[0:i]和B[0:j]的编辑距离

2).子问题的递归公式:

d[i][j]={0             i==0&&j==0

         d[i][0]=i     i>0&&j==0

         d[0][j]=j     i==0&&j>0

         min(m[i-1][j]+1,m[i][j-1]+1,m[i-1][j-1]+num) i>0&&j>0

         (num=A[i-1]=B[j-1]?0:1)

3).原问题的最优解是 d[m][n]

 

B.递归公式详解

1)若A,B均为空,则不需要做任何修改,d[i][j]=0

2)若A不为空,B为空,则需要删除A的所有内容得到B,d[i][j]=i

3) 若A为空,B不为空,则需要向A增加B的所有内容得到B,d[0][j]=j

4)若A,B两个串均不为空,则

当A[i-1]==B[j]时,需要删除A[i],d[i][j]= m[i-1][j]+1;

当A[i]==B[j-1]时,需要将B[j]加到A中,d[i][j]= m[i][j-1]+1;

当A[i-1]=B[j-1]时,d[i][j]= m[i-1][j-1]+0;否则,需要改写A[i-1],所以d[i][j]= m[i-1][j-1]+1。

所以此时d[i][j]= min(m[i-1][j]+1,m[i][j-1]+1,m[i-1][j-1]+num)

C. 使用方法:动态规划

  1. 二维数组(从递归公式左边可推断)
  2. 填表顺序(自上而下,自左向右)(因为原问题的最优解d[m][n]在右下角)

D. example A:fxpimu  B:fwrs

   表7*5

 

 

f

w

r

s

 

0

1

2

3

4

f

1

0

1

2

3

x

2

1

1

2

3

p

3

2

2

2

3

i

4

3

3

3

3

m

5

4

4

4

4

u

6

5

5

5

5

 

【算法时间及空间复杂度分析】

时间复杂度:该算法是对一个(m+1)(n+1)的表格进行填写的过程,填写每一个格d[i][j]花费的开销,只是根据 d[i-1][j], d[i][j-1], d[i-1][j-1], c[i-2][j-1]进行简单的加减运算,得到五个数字,选择其中最小的一个。所以该算法的时间复杂度为O(mn)。                                                           

空间复杂度: 该算法是对一个(m+1)(n+1)的表格进行填写的过程, 所以该算法的空间复杂度为O(mn)。

【程序运行截图】

【程序代码】

#include <iostream>

#include <string>

using namespace std;

int main()

{

   string A,B;//定义字符串A,B

   cin>>A;

   cin>>B;

   int m=A.length();//m为字符串A的长度

   int n=B.length();//n为字符串B的长度

   int a,b,c;

   static int d[2000][2000];//填表 ,d[i][j]表示A[0:i]和B[0:j]的编辑距离

 

   for(int i=0;i<=m;i++) d[i][0]=i;//填第一列

   for(int j=0;j<=n;j++) d[0][j]=j;//填第一行

   for(int i=1;i<=m;i++)

  {

     for(int j=1;j<=n;j++)

         {

           int num=(A[i-1]==B[j-1]? 0:1);

        

       a=d[i-1][j]+1;//d[i][j]上面的格

       b=d[i][j-1]+1;//d[i][j]左边的格

       c=d[i-1][j-1]+num;//d[i][j]左上的格

       d[i][j]=min(a,min(b,c));//三个格的最小值为最少字符操作数

         }

  }

    cout<<d[m][n]<<endl;

}