算法设计与分析-编辑距离问题

Posted jettle

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法设计与分析-编辑距离问题相关的知识,希望对你有一定的参考价值。

一、实践题目

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

输入格式:

第一行是字符串A,文件的第二行是字符串B。

提示:字符串长度不超过2000个字符。

输出格式:

输出编辑距离d(A,B)

输入样例:

在这里给出一组输入。例如:

fxpimu
xwrs 

输出样例:

在这里给出相应的输出。例如:

5

二、问题描述

求两个字符串的编辑距离即求将一个字符串变为另一个字符串需要进行的最少编辑次数,编辑即为进行修改,增加或删除操作。

三、算法描述

思路:对于字符串Am[a1a2...am] (a1 表示第一个字符)和字符串Bn [b1b2...bn],从最后一个字符开始比较,当am ≠ bn 时,找出 Am-1 和 Bn , Am 和 Bn-1 ,Am-1 和 Bn-1 的编辑距离,三者中最小者加 1 即为Am 和 Bn 的编辑距离。当am 等于 bn 时,将Am-1 和 Bn , Am 和 Bn-1 编辑距离加 1 再与Am-1 和 Bn-1 的编辑距离比较,取最小值。

实现:用c[i][j] 记录Ai 和 Bj  的编辑距离,递归公式为:

(1)当a≠ bj 时,c [ i ][ j ] =  min(c[ i ][ j - 1] + 1, c[ i - 1 ][ j ] + 1, c[ i - 1 ][  j - 1 ] + 1);

(2)当a= b时,c [ i ][ j ] =  min(c[ i ][ j - 1] + 1, c[ i - 1 ][ j ] + 1, c[ i - 1 ][  j - 1 ] );

c[ m ][ n ] 即为 Am 和 Bn 的编辑距离。

从公式可以看出,填充二维数组时应从左往右,从上往下填充,确保在计算某个项时其子问题已经计算过了。

最开始应初始化,使 c[ 0 ][ i ] = i,c[ j ][ 0 ] = j;

代码:

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 #define MAX 2000
 5 int c[MAX][MAX];
 6 int min(int a, int b, int c) {
 7     return (a < b ? a : b) < c ? (a < b ? a : b) : c;
 8 }
 9 int length(char *a, char *b, int m, int n) {
10 
11     for (int i = 0; i <= m; i++) {
12         c[i][0] = i;
13     }
14     for (int j = 0; j <= n; j++) {
15         c[0][j] = j;
16     }
17     for (int i = 1; i <= m; i++) {
18         for (int j = 1; j <= n; j++) {
19             if (a[i - 1] == b[j - 1]) 
20                 c[i][j] = min(c[i][j - 1] + 1, c[i - 1][j] + 1, c[i - 1][j - 1]);
21             else
22                 c[i][j] = min(c[i][j - 1], c[i - 1][j], c[i - 1][j - 1])+ 1;
23         }
24     }
25     return c[m][n];
26 }
27 
28 int main() {
29     char a[MAX], b[MAX];
30     cin >> a;
31     cin >> b;
32     int m = strlen(a);
33     int n = strlen(b);
34     cout << length(a, b, m, n);
35 }

 

四、算法时间与空间复杂度的分析

 子问题的个数为m * n, 每个子问题的算法时间复杂度为常数,故总的时间复杂度为 O(mn);

由于使用了辅助二维数组c[][], 所以空间复杂度为O(mn)。

五、心得体会

刚开始看到这道题的时候,感觉跟最长公共子序列问题有一点联系,就想到了用两个字符串中较长的字符串的长度减去两者的最长公共子序列从而得到答案,咋一看好像是没问题,自己列了几组数据也没问题,就在课上按这种方法打了代码,结果三个中有一个是答案错误,百思不得其解。后来又多写了几组数据,发现有些数据不能按照这种方法算,最后还是用了动态规划的思想,其实跟最长公共子序列问题也差不多,思路一致,就是多了一个子问题需要考虑。所以本次实验的收获就是更加了解了动态规划的思想,还有应该多用几组不一样的数据去验证自己的想法,不要急于动手打代码。

以上是关于算法设计与分析-编辑距离问题的主要内容,如果未能解决你的问题,请参考以下文章

字谜字符串编辑距离算法/代码?

计算两组标签相似度算法——levenshtein distance 编辑距离算法

动态规划的设计思想与实例(最大子段和最长公共子序列0-1背包编辑距离)

013--Floyd算法-动态规划-《算法设计技巧与分析》M.H.A学习笔记

算法---动态规划(编辑距离不同子序列动态规划总结)

Floyd算法的优缺点分析