递归与动态规划---最小编辑代价

该博客探讨了如何通过动态规划算法来求解最小编辑代价问题,即计算将字符串str1转换为str2所需的最低成本。文章通过举例解释了问题背景,明确了插入、删除和替换字符的代价,并详细描述了动态规划的解决方案,包括构造(N+1)×(M+1)的矩阵dp来存储状态转移的过程。最后,提供了Python3.5的代码实现。
摘要由CSDN通过智能技术生成

【题目】

  给定两个字符str1和str2,再给定三个整数ic,dc,rc,分别代表插入,删除和替换一个字符的代价,返回将str1编辑成str2的最小代价。

【举例】

  str1 = “abc”,str2 = “adc”,ic = 5,dc = 3,rc = 100。
  从str1编辑到str2,先删除’b’,然后插入’d’是代价最小的,所以返回8。

【基本思路】

  如果str1的长度为N,str2的长度为M,生成(N+1)×(M+1)的矩阵dp,为什么N+1,M+1,因为我们需要在字符串的开头添加一个空字符的特殊情况,dp[i][j]的值代表str1[0…i-1]编辑成str2[0…j-1]的最小代价。dp的计算如下:

  1. 矩阵的第一行表示空字符编辑成str2[0…j-1]所需要的最小代价,当然只需要插入操作即可,所以dp[0][j] = ic * j。

  2. 矩阵的第一列表示str1[0…i-1]编辑成空字符所需要的最小代价,当然只需要删除操作即可,所以dp[i][0] = dc * i。

  3. 矩阵的其他位置来自以下的三种情况:dp[i-1][j]+dc,dp[i][j-1]+ic,(dp[i-1][j-1] or dp[i-1][j-1]+rc)。
    1)dp[i-1][j] + dc,表示先删除str1[i-1],然后将str1[0…i-2]编辑成str2[0…j-1]

    2)dp[i][j-1] + ic,表示将str1[i-1]编辑成str2[0…j-2],然后再插入str2[j-1]

    3)dp[i-1][j-1] or dp[i-1][j-1]+rc,表示如果str1[i-1] != str2[j-1],则先将str1[0…i-2]编辑成str2[0…j-2]再将str1[i-1]替换成str2[j-1],如果str1[i-1] == str2[j-1],则将str1[0…i-2]编辑成str2[0…j-2]后就不需要进行替换了。

下面是用python3.5实现的代码

#最小编辑代价
#经典动态规划方法。时间复杂度O(M*N),空间复杂度O(M*N)
def minCoin(str1, str2, ic, dc, rc):
    if str1 == None or str2 == None:
        return 0
    row = len(str1) + 1
    col = len(str2) + 1
    dp = [[0 for i in range(col)] for j in range(row)]
    for i in range(row):
        dp[i][0] = i * dc
    for j in range(col):
        dp[0][j] = j * ic
    for i in range(1, row):
        for j in range(1, col):
            if str1[i-1] == str2[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)
    return dp[-1][-1]

#动态规划+空间压缩。时间复杂度O(M*N),空间复杂度O(min{M,N})
def minCoin2(str1, str2, ic, dc, rc):
    if str1 == None or str2 == None:
        return 0
    longs = str1 if len(str1) >= len(str2) else str2
    shorts = str1 if len(str1) < len(str2) else str2
    if longs == str2:
        ic, dc = dc, ic
    dp = [0 for i in range(len(shorts)+1)]
    for i in range(len(dp)):
        dp[i] = ic * i
    for i in range(1, len(longs)+1):
        leftUp = dp[0]
        dp[0] = i * dc
        for j in range(1, len(shorts)+1):
            up = dp[j]
            if longs[i-1] == shorts[j-1]:
                dp[j] = leftUp
            else:
                dp[j] = leftUp + rc
            dp[j] = min(dp[j], up+dc)
            dp[j] = min(dp[j], dp[j-1]+ic)
            leftUp = up
    return dp[-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值