【动态规划】之字符串编辑距离(难度:2星)

#include <stdio.h>

/**
 * 对于序列ST,它们之间距离定义为:对二者其一进行几次以下的操作
 * (1)删去一个字符;(2)插入一个字符;(3)改变一个字符。每进行一次操作,计数增加1
 * ST变为同一个字符串的最小计数即为它们的距离。给出相应算法。
 */
#define MIN(x,y) (x<y?x:y)

#define INF 50000

#define SL 7     //字符串s的有效长度
#define TL 5     //字符串t的有效长度

static char s[SL+2] = " acbdepo";
static char t[TL+2] = " abcde";

/**
 * 我的思路如下
 * 设子问题为:请求出字符串s的前i个字符组成的字符串与字符串tj个字符组成的字符串
 * 每次对其一进行以下其中一项操作: (1)删去一个字符;(2)插入一个字符;(3)改变一个字符。
 * 每次操作后操作数+1,最终使两个字符串相等,求最小的操作数minSum
 * 找出边界:显然i=0,minSum=j,因为i=0,所需要的就是连续插入j次对应字符串t的字符,
 * 同理j=0时也一样
 */
//递归
int solve_1(int i, int j){
    if (i == 0)
        return j;
    if (j == 0)
        return i;
    //ij大于0的情况
    int cost = s[i] == t[j] ? 0 : 1;
    int del = solve_1(i-1, j) + 1;
    int add = solve_1(i, j-1) + 1;
    int upd = solve_1(i-1, j-1) + cost;
    return MIN(del, MIN(add, upd));
}

//递归+记忆数组的dp
static int memo[SL+1][TL+1];
int solve_2(int i, int j){
    if (i == 0)
        return memo[i][j] = j;
    if (j == 0)
        return memo[i][j] = i;
    if (memo[i][j] < INF)
        return memo[i][j];

    //ij大于0的情况
    int cost = s[i] == t[j] ? 0 : 1;
    int del = solve_2(i-1,j) + 1;
    int add = solve_2(i,j-1) + 1;
    int upd = solve_2(i-1,j-1) + cost;
    return memo[i][j] = MIN(del, MIN(add, upd));
}

//递推
static int dp[SL+1][TL+1];
int solve_3(){
    for (int i = 0; i <= SL; ++i) {
        dp[i][0] = i;
    }
    for (int j = 0; j <= TL; ++j) {
        dp[0][j] = j;
    }
    for (int i = 1; i <= SL; ++i) {
        for (int j = 1; j <= TL; ++j) {
            if (s[i] == t[j])
                dp[i][j] = dp[i-1][j-1];
            else{
                int del = dp[i-1][j] + 1;
                int add = dp[i][j-1] + 1;
                int upd = dp[i-1][i-1] + 1;
                dp[i][j] = MIN(del, MIN(add, upd));
            }
        }
    }
    return dp[SL][TL];
}


int main() {
    printf("solve_1:%d\n", solve_1(SL, TL));

    for (int i = 0; i <= SL; ++i) {
        for (int j = 0; j <= TL; ++j) {
            memo[i][j] = INF;
        }
    }
    printf("solve_2:%d\n", solve_2(SL, TL));

//    for (int i = 0; i <= SL; ++i) {
//        for (int j = 0; j <= TL; ++j) {
//            printf("%d ",memo[i][j]);
//        }
//        printf("\n");
//    }

    printf("solve_3:%d\n", solve_3());

    return 0;
}

运行结果:

solve_1:4
solve_2:4
solve_3:4




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值