最小编辑代价——动态规划

题目描述
给定两个字符串str1和str2,再给定三个整数ic,dc和rc,分别代表插入、删除和替换一个字符的代价,请输出将str1编辑成str2的最小代价。

示例1
输入 “abc”,“adc”,5,3,2
返回值 2

示例2
输入 “abc”,“adc”,5,3,100
返回值 8

备注:
1≤|str1|,|str2|≤5000
1≤ic,dc,rc≤10000

这题好难,看了网上各路大神的代码最后模仿写的。
主要创建一个数组dp,记录str1子串转化为str2子串的最小代价。dp[i][j]表示长度为i的第一个字符串编辑成长度为j的第二个字符串消耗的最小代价。
假设str1的长度为len1,str2的长度为len2,首先生成大小为(len1+1)*(len2+1)的矩阵dp,dp[i][j]的值代表str1[0…i-1]编辑成str2[0…j-1]的最小代价。
比如str1=“ab12cd3”,str2=“abcdf”,ic=5,dc=3,rc=2。
在这里插入图片描述
如果str1[i-1] == str2[j-1],则只需要将前i-1个字符转换为前j-1个字符即可,最后一个字符不动:dp[i][j] = dp[i-1][j-1]
如果str1[i] != str2[j]有三类操作可以使得str1变成str2,取其中的最小值:
1.插入:将i个字符串转变为前j-1个字符串在插入第j个字符 dp[i][j-1]+ic
dp[i][j-1]是实现字符串str1[0…i-1]转变为字符串str2[0…j-2]的最小代价,再插入一个字符,就实现str1到str2的转变。
2.删除:将i-1个字符串转换为前j个字符串删除第i个字符 dp[i-1][j]+id
dp[i-1][j]是实现字符串str1[0…i-2]转变为字符串str2[0…j-1]的最小代价,再删除一个字符,就实现str1到str2的转变。
3.替换:将i-1个字符串转换为前j-1个字符串替换掉第i个字符为第j个字符 dp[i-1][j-1]+rc
dp[i-1][j-1]是实现字符串str1[0…i-2]转变为字符串str2[0…j-2]的最小代价,再更改一个字符,就实现str1到str2的转变。

例如上图中的第二行第三列的5,
插入操作是将a先转变成a,代价是dp[1][1]=0,再插入字符b;
删除操作是将空字符串先转变为ab,代价是dp[0][2]=10,由于原第一个字符串有a,因此需要删除一个字符;
替换操作是将空字符串先转变为a,代价是dp[0][1]=5,再将a转变为b需要替换操作;

参考了的链接:
https://www.cnblogs.com/lutaishi/p/13436213.html
https://www.cnblogs.com/sidewinder/p/13750134.html
https://www.nowcoder.com/questionTerminal/05fed41805ae4394ab6607d0d745c8e4?answerType=1&f=discussion

C++实现:

#include<algorithm>
#include<vector>
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) {
        // write code here
        int len1=str1.size();
        int len2=str2.size();
        vector<vector<int> > dp(len1 + 1, vector<int>(len2 + 1));
        int i=0,j=0;
        dp[0][0]=0;
        for(i=0,j=0;j<=len2;j++) //计算第一行,全是插入操作
        {
            dp[i][j]=ic*j;
        }
        for(i=0,j=0;i<=len1;i++) //计算第一列,全是删除操作
        {
            dp[i][j]=dc*i;
        }
        for(i=1;i<=len1;i++)
        {
            for(j=1;j<=len2;j++)
            {
                if(str1[i-1]==str2[j-1])
                {
                    dp[i][j]=dp[i-1][j-1];
                }
                else{
                int Min;
                Min=min(dp[i-1][j]+dc,dp[i][j-1]+ic);
                Min=min(Min,dp[i-1][j-1]+rc);
                dp[i][j]=Min;
                }
            }
        }
        return dp[len1][len2];
    }
    
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值