题目描述
给定两个字符串str1和str2,再给定三个整数ic,dc和rc,分别代表插入、删除和替换一个字符的代价,请输出将str1编辑成str2的最小代价。
输入描述:
输出三行,第一行和第二行均为一行字符串,分别表示两个字符串str1,str2。(1≤length(str1),length(str2)≤5000)。第三行为三个正整数,代表ic,dc和rc。(1<=ic<=10000、1<=dc<=10000、1<=rc<=10000)
输出描述:
输出一个整数,表示编辑的最小代价。
示例1
输入
abc adc 5 3 2
输出
2
示例2
输入
abc adc 5 3 100
输出
8
示例3
输入
abc abc 5 3 2
输出
0
备注:
时间复杂度O(n∗m),空间复杂度O(n)。(n,m代表两个字符串长度)
//方法1:
//dp[i][j]定义为s1[0..i-1]编辑成s2[0..j-1]的最小代价
//O(mn) O(mn)
#include<bits/stdc++.h>
using namespace std;
int main(){
string s1,s2;
cin>>s1>>s2;
int ic,dc,rc;
cin>>ic>>dc>>rc;
int row=s1.size()+1;
int col=s2.size()+1;
vector<vector<int>> dp(row,vector<int>(col,0));
for(int i=1;i<row;i++){
dp[i][0]=i*dc;
}
for(int j=1;j<col;j++){
dp[0][j]=j*ic;
}
for(int i=1;i<row;i++){
for(int j=1;j<col;j++){
if(s1[i-1]==s2[j-1]){
dp[i][j]=dp[i-1][j-1];
}else{
dp[i][j]=dp[i-1][j-1]+rc;
}
dp[i][j]=min(dp[i][j],dp[i][j-1]+ic);
dp[i][j]=min(dp[i][j],dp[i-1][j]+dc);
}
}
cout<<dp[row-1][col-1]<<endl;
return 0;
}
//方法2:优化空间
//dp[i][j]依赖于dp[i-1][j-1]、dp[i-1][j]、dp[i][j-1]
//O(mn) O(min(m,n))
#include<bits/stdc++.h>
using namespace std;
int main(){
string s1,s2;
cin>>s1>>s2;
int ic,dc,rc;
cin>>ic>>dc>>rc;
//较短的字符串作为列
if(s1.size()<s2.size()){ //s2较长就交换ic和dc的值
swap(ic,dc);
swap(s1,s2); //s1作为行,s2作为列(交换后,s2较短)
}
vector<int> dp(s2.size()+1);
for(int j=1;j<=s2.size();j++){
dp[j]=j*ic;
}
for(int i=1;i<=s1.size();i++){
int pre=dp[0]; //pre表示上一行最左边的值,最开始是未更新的dp[0]
dp[0]=i*dc; //更新当前行的dp[0]
for(int j=1;j<=s2.size();j++){
int tmp=dp[j]; //记录上一行的dp[j]
if(s1[i-1]==s2[j-1]){
dp[j]=pre;
}else{
dp[j]=pre+rc;
}
dp[j]=min(dp[j],dp[j-1]+ic);
dp[j]=min(dp[j],tmp+dc);
pre=tmp; //pre变为上一行的dp[j],是下一次循环的左上角的值
}
}
cout<<dp[s2.size()]<<endl;
return 0;
}