看到网上这个大佬的著作2020年华为春招真题(最短编辑距离)详解+Java代码实现(校招,Minimum Edit Distance,Levenshtein距离,代码,原理解释)后,
2020年3月4日的华为校园春招的真题第3题——
编辑距离改编题:输入n,接下来2n行,前n行表示待修改文章,后n行表示已修改文章。输出从待修改文章到已修改文章最少编辑的次数。删除、添加、替换一个字符都算一次编辑。
例如输入:
2
abcdef
234
bcdg
123
则输出:
5
解释:abcdef–> 删除a --> bcdef -->删除e -->bcdf -->f替换成g ,编辑3次
234–>插入1 -->1234–>删除4–> 123,编辑2次
因此最终输出5次
解法:动态规划的最短编辑距离
用C++实现了
#include<iostream>
#include<string.h>
#include<vector>
# define Min(x,y) (x<y?x:y)
using namespace std;
int minimunEditDistance(string s1, string s2) {
//新建一个二维数组,用于存取两字符串的各个子字符串之间的最短编辑距离
//其中新建的二维数组的行列都+1是因为最短编辑距离的矩阵的子字符串从空串""开始,把空串""考虑进去,因此行列都+1
int** minMatrix = new int* [s1.size() + 1];
for (int i = 0; i <= s1.size(); i++)
minMatrix[i] = new int[s2.size() + 1];
//初始化
//minMatrix[i][0]表示该两个子字符串互相转换的最小编辑距离
for (int i = 0; i <= s1.size(); i++) {
minMatrix[i][0] = i;
}
//minMatrix[0][j]表示该两个子字符串互相转换的最小编辑距离
for (int j = 0; j <= s2.size(); j++) {
minMatrix[0][j] = j;
}
//建一个二层循环嵌套,分别比较并计算str1和str2的子字符串都不是空串""时互相转换的最小编辑距离
//注意此二层循环嵌套的2个计数器i和j都是从1开始的,因为上面已经对二维数组的行列包含0的情况赋值最小编辑距离了
//注意此二层循环嵌套的2个for循环条件都是字符串长度+1,+1是因为最短编辑距离的矩阵的子字符串从空串""开始,把空串""考虑进去,因此行列都+1
for (int i = 1; i < s1.size() + 1; i++) {
for (int j = 1; j < s2.size() + 1; j++) {
//若某两个子字符串的最后一个字符相同,那么此时此两个子字符串的最短编辑距离等价于:没有最后一个相同字符的两个子字符串互相转换的最短编辑距离
//例如"lalan"和"legen"的最后一个字符都是"n",则 "lalan"和"legen"的最小编辑距离 等于 "lala"和"lege"的最小编辑距离
if (s1[i - 1] == s2[j - 1]) {
minMatrix[i][j] = minMatrix[i - 1][j - 1];
}
//若某两个子字符串的最后一个字符不相同,那么此时此两个子字符串的最短编辑距离等价于:minMatrix[i-1][j]和minMatrix[i][j-1]和minMatrix[i-1][j-1]之间的最小值,再+1
//最后+1是因为最后一个字符不相同。若是minMatrix[i-1][j-1]+1,则是某两个子字符串的最后两个不同字符进行1次替换字符操作,从而让该两字符相同;
//若是minMatrix[i-1][j]+1或minMatrix[i][j-1]+1,则是某两个子字符串的两个不同字符进行1次插入/删除字符操作;
else {
minMatrix[i][j] = Min(
Min(minMatrix[i - 1][j], minMatrix[i][j - 1]), // 插入/删除
minMatrix[i - 1][j - 1] //替换
) + 1;
}
}
}
//最后返回的是int型的两个字符串互相转换的最小编辑距离,该值是行列分别是str1和str2的长度的二维数组minMatrix的元素值
return minMatrix[s1.size()][s2.size()];
}
int main() {
int n = -1;
cin >> n;
vector <string> strs;
string str;
for (int i = 0; i < n; i++) {
cin >> str;
strs.push_back(str);
}
int sum = 0;
for (int i = 0; i < strs.size(); i++) {
cin >> str;
sum += minimunEditDistance(strs[i], str);
}
cout << sum << endl;
}
推荐相关:求最长公共子序列
动态规划–最长公共子序列