题目描述
给定两个字符串str1和str2,再给定三个整数ic,dc和rc,分别代表插入、删除和替换一个字符的代价,请输出将str1编辑成str2的最小代价。
题目大意
- 经典动态规划题,与题目有相似之处https://blog.csdn.net/lr_shadow/article/details/115003239
- 动态规划的五步骤:
- 确定dp数组和下标含义:dp[i][j]代表以i-1结尾的字符串word1和以j-1为结尾的字符串word2
- 确定递推公式:
关于下式中dp[i][j-1]后面是加上ic还是dc,这个没有固定格式,此处这样写是为了跟初始化dp数组方式进行统一,初始化时,dp[i][0]代表word1前i个字符,word2前0个字符,采取删除word1中最后当前字符的方式进行更新,同理,在核心代码中dp[i][j]到dp[i-1][j]也为删除字符的方式达到统一
d p [ i ] [ j ] = { d p [ i − 1 ] [ j − 1 ] ( i f w o r d 1 [ i − 1 ] = = w o r d 2 [ j − 1 ] ) e l s e m i n ( m i n ( d p [ i ] [ j − 1 ] + i c , d p [ i − 1 ] [ j ] + d c ) , d p [ i − 1 ] [ j − 1 ] + r c ) dp[i][j]= \left \{ \begin{array} {c}dp[i-1][j-1]{\quad}(if{\quad}word1[i-1]==word2[j-1]) \\else \\min(min(dp[i][j-1]+ic,dp[i-1][j]+dc),dp[i-1][j-1]+rc){\quad} \end{array} \right. dp[i][j]=⎩⎨⎧dp[i−1][j−1](ifword1[i−1]==word2[j−1])elsemin(min(dp[i][j−1]+ic,dp[i−1][j]+dc),dp[i−1][j−1]+rc)
- 继续
- 如何定义和初始化dp数组
- 确定遍历顺序
- 举例推导dp数组
动态规划
- 在初始化的时候,我们需要对dp[i][0]和dp[0][j]进行遍历,因为此时是数组dp的最初状态,即对word1或word2是空串是进行初始化
- 在确定完这五步后,思路就清晰了
class Solution {
public:
/**
* min edit cost
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @param ic int整型 insert cost
* @param dc int整型 delete cost
* @param rc int整型 replace cost
* @return int整型
*/
int minEditCost(string str1, string str2, int ic, int dc, int rc) {
int len1 = str1.size(), len2 = str2.size();
vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1, 0));
for (int i = 1; i <= len1 ; ++i){
dp[i][0] = i * dc;
}
for (int i = 1 ; i <= len2; ++i){
dp[0][i] = i * ic;
}
for (int i = 1 ; i <= len1; ++i){
for (int j = 1 ; j <= len2 ; ++j){
if (str1[i - 1] == str2[j - 1])
dp[i][j] = dp[i - 1][j - 1];
else{
dp[i][j] = min(min(dp[i - 1][j - 1] + rc, dp[i - 1][j] + dc), dp[i][j - 1] + ic);
}
}
}
return dp[len1][len2];
}
};
复杂度分析
- 时间复杂度:O(m*n)。n为数组的长度
- 空间复杂度:O(m*n)。n为数组的长度,维护了一个二维dp数组,二维长度为word1的长度,二维中的一维数组为word2的长度