动态规划之编辑距离

来源:互联网 发布:东方网络董事长 编辑:程序博客网 时间:2024/06/06 23:59

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

问题分析假设有两个字符串s1[1, s1.length()]和s2[1, s2.length()],倘若s1[s1.length()] == s2[s2.length()],那么即只需要计算s1[1, s1.length() - 1] 替换成 s2[1, s2.length() - 1]需要变换的次数即可。并以此类推下去。那么如果不相等的时候,就需要进行三种基本操作:

1. 插入一个字符2.删除一个字符;3.更改一个字符。

 那么这三个操作需要的步骤最少的那个操作即为两个字符串长度不相等情况下该点的编辑距离。(动态规划的思想)


 

【解决方案】 先定义了一个记录结果的二维数组result[s1.length()+1][s2.length()+1],(之所以要设置多一位来保存数据,是考虑了当两个字符串其中一个或两个为空串时的情况)。显然,当j = 0时,result[i][0] = i;同理,当i = 0时,result[0][j] = j。

  那么递归式为   result[i][j] = {              0           i = j = 0;

      i            j = 0;

      j            i = 0;

min( addition, deletion, sub)    }

其中addition为增加一个字符的操作,定义为int addition = result[i][j - 1] + 1

deletion为删除一个字符的操作,定义为int deletion = result[i - 1][j] + 1

sub为替换一个字符的操作,定义为int sub = result[i - 1][j - 1] + isEquals

(isEquals = 0或1,当s1[i]等于s2[j]时(实际操作时为s1[i - 1]和s2[j - 1]相等时,因为是从i=j=1开始循环)取0, 表示接下来无需操作;反之则表示接下来需要操作, 于是编辑距离加1。以下用一个例子说明result的记录过程:

    如:  abcc 与 abxy  

   下标       0   1   2   3   4

                 0   a   b   c   c

     0    0    0   1   2   3   4

     1    a    1   0   1   2   3

     2    b    2   1   0   1   2

     3    x    3   2   1   1   2

     4    y    4   3   2   2   2

可见,最后的输出结果为result[s1.length()][s2.length()]。

 

【具体实现代码】

int result[lengthS1 + 1][lengthS2 + 1];

//i = 0j > 0时,result[0][j] = j; 反之同理,故先在此声明

for (int i = 0; i <= lengthS1; i++) {

result[i][0] = i;

}

for (int j = 0; j <= lengthS2; j++) {

result[0][j] = j;

}

 

for (int i = 1; i <= lengthS1; i ++) {

for (int j = 1; j <= lengthS2; j ++) {

int isEquals = s1[i - 1] == s2[j - 1] ? 0 : 1;

//增加一个数

int addition = result[i][j - 1] + 1;

//删除一个数

int deletion = result[i - 1][j] + 1;

//替换一个数

int sub = result[i - 1][j - 1] + isEquals;

result[i][j] = min(addition, deletion, sub);

}

}


【思维误区】我刚开始的时候,是跟以前做题的习惯一样,喜欢从数组的下标0开始标记,一直到length - 1。于是在编辑距离问题上就会发现进了一个大坑。是因为当某一字符串为空串时,用1作为开始下标的话,编辑距离应该为非空串字符串的长度;而若采用下标0为开始下标时,则编辑距离会比正确答案少1。


原创粉丝点击