题目
给定一个源串和目标串,能够对源串进行如下操作:
1.在给定位置上插入一个字符
2.替换任意字符
3.删除任意字符
写一个程序,返回最小操作数,使得对源串进行这些操作后等于目标串,源串和目标串的长度都小于2000。
思路
如果有两个串 A = xabcdae 和 B = xfdfa,它们的第一个字符是相同的,只要计算A[2…7] = abcdae 和 B[2…5] = fdfa的距离就可以了。但是如果两个串的第一个字符不相同,那么可以进行如下的操作(lenA和lenB分别是字符串A和B的长度):
(1)删除A串的第一个字符,然后计算A[2…lenA]和B[1…lenB]的距离。
(2)删除B串的第一个字符,然后计算A[1…lenA]和B[2…lenB]的距离。
(3)修改A串的第一个字符为B串的第一个字符,然后计算A[2…lenA]和B[2…lenB]的距离。
(4)修改B串的第一个字符为A串的第一个字符,然后计算A[2…lenA]和B[2…lenB]的距离。
(5)增加B串的第一个字符到A串的第一个字符之前,然后计算A[1…lenA]和B[2…lenB]的距离。
(6)增加A串的第一个字符到B串的第一个字符之前,然后计算A[2…lenA]和B[1…lenB]的距离。
在这个题目中,我们并不在乎两个字符串变得相等之后的字符串是什么样的。所以,我们可以将上面的6个步骤简化为:
(1)一步操作之后,再将A[2…lenA] 和 B[1…lenB]变成相同的字符串。
(2)一步操作之后,再将A[1…lenA] 和 B[2…lenB]变成相同的字符串。
(3)一步操作之后,再将A[2…lenA] 和 B[2…lenB]变成相同的字符串。
这样,很快就可以完成一个递归程序:
代码
#include <iostream>
using namespace std;
class Solution {
public:
int StrDistance(string A,string B){
int sizeA = A.size();
int sizeB = B.size();
return StrDistance(A,0,sizeA-1,B,0,sizeB-1);
}
private:
int StrDistance(string A,int startA,int endA,string B,int startB,int endB){
if(startA > endA){
if(startB > endB){
return 0;
}
else{
return endB - startB + 1;
}
}
if(startB > endB && startA <= endA){
return endA - startA + 1;
}
if(A[startA] == B[startB]){
return StrDistance(A,startA+1,endA,B,startB+1,endB);
}
else{
int len1 = StrDistance(A,startA+1,endA,B,startB,endB);
int len2 = StrDistance(A,startA,endA,B,startB+1,endB);
int len3 = StrDistance(A,startA+1,endA,B,startB+1,endB);
return min(min(len1,len2),len3)+1;
}
}
};
int main() {
Solution solution;
string str1("xabcdae");
string str2("xfdfa");
cout<<solution.StrDistance(str1,str2)<<endl;
}
上面的思路还可以进行优化。在递归的过程中,有些数据被重复计算了。比如,如果我们开始调用StrDistance(A,1,3,B,1,3)
下图是部分展开的递归调用:
可以看到,圈中的两个子问题被重复计算了。为了避免这种不必要的重复计算,可以把子问题计算后的解储存起来。
思路二
编辑距离是动态规划里面的经典题目。 Edit[i][j]为word1[0..i-1]和word2[0..j-1]的最小编辑数。
状态转移方程:
代码二:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size();
int n = word2.size();
int Edit[m+1][n+1];
for(int i = 0;i <= m;++i){
Edit[i][0] = i;
}
for(int i = 0;i <= n;++i){
Edit[0][i] = i;
}
for(int i = 1;i <= m;++i){
for(int j = 1;j <= n;++j){
if(word1[i-1] == word2[j-1]){
Edit[i][j] = Edit[i-1][j-1];
}
else{
Edit[i][j] = 1 + min(Edit[i-1][j-1],min(Edit[i-1][j],Edit[i][j-1]));
}
}
}
return Edit[m][n];
}
};
int main(){
Solution solution;
string str1("ab");
string str2("bc");
cout<<solution.minDistance(str1,str2)<<endl;
return 0;
}
<script type="text/javascript">
$(function () {
$('pre.prettyprint code').each(function () {
var lines = $(this).text().split('\n').length;
var $numbering = $('<ul/>').addClass('pre-numbering').hide();
$(this).addClass('has-numbering').parent().append($numbering);
for (i = 1; i <= lines; i++) {
$numbering.append($('<li/>').text(i));
};
$numbering.fadeIn(1700);
});
});
</script>
分享到:
相关推荐
输入任意两个字符串,计算它们的编辑距离。 编辑距离是指两个字符串之间,由一个转换为另一个所需的最少编辑操作次数。许可的编辑操作包括字符的替换、插入和删除。
将字符串A变换为字符串B 所用的最少字符操作数称为字符串A到B 的编辑距离,记为d(A,B)。试设计一个有效算法,对任给的2 个字符串A和B,计算出它们的编辑距离d(A,B)。 编程任务: 对于给定的字符串A和字符串B,编程...
自己总结的面试常见题 C++字符串处理 自己总结的面试常见题 C++字符串处理
试验题目:近似字符串匹配问题计算两个字符串s1+ch1, s2+ch2的编辑距离有这样的性质: 1. d(s1,””) = d(“”,s1) = |s1| d(“ch1”,”ch2”) = ch1 == ch2 ? 0 : 1; 2. d(s1+ch1,s2+ch2) = min( d(s1,s2)+ ch1==...
计算两个字符串的编辑距离 -- 快速算法
VC实现字符串编辑距离计算,距离计算分为变换、删除、插入三种。
编辑距离算法,比较字符串相似度 pb11.5版本
C#面试题字符串转换整数
算法-动态规划- 线性 DP- 字符串编辑距离(包含源程序).rar
一些与字符串有关的常考的面试题,用C语言实现的
自己整理的校招笔试面试时,主要的字符串题型。
1.字符串高频面试题精讲1.字符串高频面试题精讲1.字符串高频面试题精讲
Levenshtein:快速计算编辑距离以及字符串的相似度
用于计算两个字符串的最小距离,这两个字符串可以在任意位置插入任意多个空格,用它们长度相等的两个子串求最小距离
部分公司的面试题。里面有很详细的关于字符串的面试题,希望对大家有用。
参考清华大学的《算法设计与分析》课后的习题,输入两个字符串后输出其编辑距离。
设A和B是2个字符串.要用最少的字符操作将字符串A转换为字符...将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B).试设计一个有效算法,对任给的2个字符串A和B,计算出他们的编辑距离d(A,B)
定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。 如把字符串abcdef左旋转2位得到字符串cdefab。请实现字符串左旋转的函数。 国外服务器租用商要求时间对长度为n的字符串操作的复杂度为O(n),...
IT公司面试常见题,字符串左旋转问题,该代码可在VC6.0平台上直接编译运行,测试已经通过,代码 有详细注释,及思路解析……希望对大家有用……
开发计算两个字符串间的编辑距离,LCS距离和N-gram距离的函数。 (1)编辑距离 字符串a和b的编辑距离ED(i,j)表示把字符串a转换成b所需要的最少操作次数,这些操作可以是:插入一个字符,删除一个字符,替换一个字符...