动态规划--编辑距离问题

一、问题描述

设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

二、算法分析

我们把问题一步步执行,每一步的执行都依赖上一步的决策(删除、插入、替换),即子问题具有重叠性,同时子问题的求解都有最佳决策,所以这是一个动态规划问题。这里定义一个二维数组d[i][j]保存操作,表示字符串i到字符串j的距离。

1)假如i长度大于j进行删除做作使i变成j, 则此时d[i][j] = d[i - 1][j] + 1;

2)假如i长度小于j进行插入操作,即删除j末尾元素, 使i与j相等, 则此时d[i][j] = d[i][j - 1] + 1;

3) 假如i长度等于j,则判断i和j最后一个元素相不相等。若相等则d[i][j] = d[i-1][j-1] + 1.

得出递归公式:d[i][j] =min(d[i-1][j-1] + diff(), d[i][j-1]+1, d[i-1][j]+1)即i到j的最佳决策等于:上一步的最佳决策和对这一步决策(删除、插入、替换)的最小值。

三、代码

 

#include <iostream>
#include <cstring>
using namespace std;

int min(int a, int b, int c) {
    int temp = a < b ? a : b;
    return temp < c ? temp : c;
}
int m(string a, string b) {
    int E[a.length() + 1][b.length() + 1];
    // 初始化二维数组
    for (int i = 0; i <= a.length(); i++) {
        E[i][0] = i;
    }
    for (int i = 0; i <= b.length(); i++) {
        E[0][i] = i;
    }
    //算法实现
    for (int i = 1; i <= a.length(); i++) {
        for (int j = 1; j <= b.length(); j++) {
            int diff = (a[i - 1] == b[j - 1] ? 0 : 1);//diff表示相同则加0,不相同加1
            E[i][j] = min(E[i - 1][j] + 1, E[i][j - 1] + 1, E[i - 1][j - 1] + diff);
        }
    }
    return E[a.length()][b.length()];
}
int main() {
    string i, j;
    cin >> i >> j;
    cout << d(i, j) << endl;

四、时空分析

因为用了一个数组存储两层for,所以时间复杂度为O(i*j),空间复杂度为O(i*j)。

五、结对总结

通过互相讲述做题过程,从而对题目有了一个更加清晰的认知,也对做题方法起到了很好的总结作用。 

posted @ 2018-11-05 18:36  Adom_ye  阅读(963)  评论(0编辑  收藏  举报