最小编辑代价(最小编辑距离)

题目描述:

给定两个字符串str1和str2,再给定三个整数ic,dc,rc,分别代表插入、删除、替换一个字符的代价,返回将str1编辑成str2的最小代价。
举例:
str1=”abc” str2=”adc” ic=5 dc=3 rc=2,从”abc”编辑到”adc”把b替换成d代价最小,为2;
str1=”abc” str2=”adc” ic=5 dc=3 rc=10,从”abc”编辑到”adc”,先删除b再插入d代价最小,为8;

分析:

经典动态规划方法,利用二维数组dp[][]保存动态规划表;
假设str1长度为M[0…..M-1],str2长度为N[0…….N-1],dp大小为(M+1)*(N+1);

dp[i][j]表示str1[0……i-1]编辑成str2[0……j-1]的最小编辑代价,dp大小为(M+1)*(N+1)是为了从空串开始计算,即dp[0][0]表示空串编辑到空串的最小编辑代价。

如何生成dp[][]:

1.dp[0][0]表示空串编辑成空串,故dp[0][0]=0;

2.求第一行dp[0][j],空串编辑成str2[0….j-1],则dp[0][j]=ic*j;

3.求第一列dp[i][0],str1[0……i-1]编辑成空串,则dp[i][0]=dc*i;

4.求dp[i][j],即str1[0….i-1]编辑成str2[0…..j-1],四种可能的途径:

<1>str1[0….i-1]先编辑成str2[0…..j-2],再由str2[0…..j-2]到str2[0…..j-1],即dp[i][j-1]+ic;

<2>str1[0….i-1]先编辑成str1[0…..i-2],再由str1[0…..i-2]到str2[0…..j-1],即dc+dp[i-1][j];

<3>如果str1[i-1]==str2[j-1],则dp[i][j]=dp[i-1][j-1];

   如果str1[i-1]!=str2[j-1],则dp[i][j]=dp[i-1][j-1]+rc;

选择上面四个中最小的值作为dp[i][j],时间复杂度O(MN),空间复杂度O(MN)。最小编辑距离为dp[M][N]。

public class MinCost {
    public int findMinCost(String A, int n, String B, int m, int ic, int dc, int rc) {
        if(A==null||B==null)
            return 0;
        if(n==0) return m*ic;
        if(m==0) return n*ic;
        int[][] dp=new int[n+1][m+1];
        dp[0][0]=0;
        for(int i=1;i<m+1;++i){
            dp[0][i]=ic*i;
        }
        for(int i=1;i<n+1;++i){
            dp[i][0]=dc*i;
        }
        for(int i=1;i<n+1;++i){
            for(int j=1;j<m+1;++j){
                if(A.charAt(i-1)==B.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1];
                }
                else{
                    dp[i][j]=dp[i-1][j-1]+rc;
                }
                dp[i][j]=Math.min(dp[i][j],dp[i-1][j]+dc);
                dp[i][j]=Math.min(dp[i][j],dp[i][j-1]+ic);
            }
        }
        return dp[n][m];
    }
class MinCost {
public:
    int findMinCost(string A, int n, string B, int m, int c0, int c1, int c2) {
        int dp[n+1][m+1];
        dp[0][0] = 0;
        for(int i=1;i<=n;i++)
            dp[i][0] = dp[i-1][0] + c1;
        for(int j=1;j<=m;j++)
            dp[0][j] = dp[0][j-1] + c0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(A[i-1] == B[j-1])
                    dp[i][j] = dp[i-1][j-1];
                else
                    dp[i][j] = min(dp[i-1][j-1]+c2, min(dp[i-1][j]+c1, dp[i][j-1]+c0));            
            }         
        return dp[n][m];
    }
};
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值