【動態規劃】之字符串編輯距離(難度: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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章