一、问题描述
设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 #include
using namespacestd;int min(int a, int b, intc) {int temp = a < b ?a : b;return temp < c ?temp : c;
}int m(string a, stringb) {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);
}
}returnE[a.length()][b.length()];
}intmain() {stringi, j;
cin>> i >>j;
cout<< d(i, j) << endl;
四、时空分析
因为用了一个数组存储两层for,所以时间复杂度为O(i*j),空间复杂度为O(i*j)。
五、结对总结
通过互相讲述做题过程,从而对题目有了一个更加清晰的认知,也对做题方法起到了很好的总结作用。