1. 程式人生 > >動態規劃C++實現--最小編輯代價

動態規劃C++實現--最小編輯代價

題目:給定兩個字串 str1 和 str2,再給定三個整數 ic, dc 和 rc,分別代表插入、刪除和替換1個字元的代價,

          返回 str1 編輯成 str2 的代價。

舉例

        str1 = "abc", str2 = "adc", ic = 5, dc = 3, rc = 2.   : "b"替換成"d"代價為 2

        str1 = "abc", str2 = "adc", ic = 5, dc = 3, rc = 100    :  先刪除"b",再插入"d"代價為8

        str1 = "abc", str2 = "abc"  兩個字串相同,不用編輯了,代價為0.

方法

       如果 str1 的長度為 M,str2的長度為 N,採用動態規劃的方法,時間複雜度為 O(M*N) ,額外的空間複雜度為O(M*N)

       首先生成動態矩陣 dp[M+1][N+1],其中 dp[i][j] 表示 st1[0,...,i-1] 編輯成 str2[0,...,j-1]的最小代價。

     1. 首先動態矩陣的初始值 dp[0][0] = 0

     2. 動態矩陣的第一列 dp[0,...,M-1][0] . dp[i][0] 表示 str1[0,...,i-1]編輯成空串的代價,即刪除(dc)所有字元,

         dp[i][0] = dc * i

     3. 動態矩陣的第一行 dp[0][0,...,N-1] . dp[0][j] 表示 空串編輯成 str2[0,...,j-1]的代價,即插入(ic)所有字元,

         dp[0][j] = ic * j

     4. 其他位置進行填充 dp[i][j]

         ① str1 先刪除(dc)一個字元,dp[i][j] = dc + dp[i-1][j] ;

                 具體來說,str1[0,...,i-1] 先刪除 str[i-1],得到 str1[0,...,i-2],  再由str1[0,..., i-2] 編輯成 str2[0,...,j-1].   (dp[i-1][j])

         ② str2 後插入(ic)一個字元 ,dp[i][j] = dp[i][j-1] + ic ;

                 具體來說,str1[0,...,i-1] 先編輯成 str2[0,..., j-2] (dp[i][j-1]), 再由 str2[0,...,j-2] 插入一個 str2[j-1] 編輯成str2[0,...,j-1]

         ③ 若 str1[i-1]  != str2[j-1] ,替換(rc) str1[i-1] 的字元, dp[i][j] = dp[i-1][j-1] + rc

             若 str1[i-1] == str2[j-1] , dp[i][j] = dp[i-1][j-1]

程式碼如下:

// 最小編輯代價 <動態規劃> <複雜度0(M*N)>
#include<bits/stdc++.h>
using namespace std;
int mincost1(string str1, string str2, int ic, int dc, int rc);

int main(){
    string str1, str2;
    cin>>str1;
    cin>>str2;
    int ic = 5;    //插入一個字元的代價
    int dc = 3;    //刪除一個字元的代價
    int rc = 2;    //替換一個字元的代價
    int result = mincost1(str1, str2, ic, dc, rc);
    cout<< result;
    return 0;
}

int mincost1(string str1, string str2, int ic, int dc, int rc){
    int row = str1.size() + 1;
    int col = str2.size() + 1;
    vector<vector<int>> dp(row, vector<int>(col, 0));
    //考慮邊界,第一列,第一行
    for(int i = 1; i < row; i++){
        dp[i][0] = dc * i;
    }
    for(int j = 1; j < col; j++){
        dp[0][j] = ic * j;
    }
    //其他位置進行從左到右,從上到下的填充
    for(int i = 1; i < row; i++){
        for(int j = 1; j < col; j++){
            if(str1[i-1] != str2[j-1]){
                dp[i][j] = dp[i-1][j-1] + rc;
            }else{
                dp[i][j] = dp[i-1][j-1];
            }
            dp[i][j] = min(dp[i][j], dc + dp[i-1][j]);
            dp[i][j] = min(dp[i][j], dp[i][j-1] + ic);
        }
    }
    return dp[row-1][col-1];
}
/* input
ab12cd3
abcdf
*/
/* output
8
*/

編譯環境:codeblocks

輸入:


輸出:


未完:結合空間壓縮的方法,可以將額外空間複雜度降低為O(min(M,N))