1. 程式人生 > >演算法學習——動態規劃 例題:兩字串轉換權最小問題(java)

演算法學習——動態規劃 例題:兩字串轉換權最小問題(java)

題目 :

給定兩個字串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=100.從abc編輯成adc,先刪除d,然後插入d是代價最小的, 所以返回8.

動態規劃:

假設str1的長度為m,str2的長度為N,首先生成大小為(M+1)*(n+1)的矩陣dp,dp[i][j]的值代表str1[0...i-1]編輯成str2[0....j-1] 的最小代價,

思想理解(本人的通俗理解):

 動態規劃無非就是動態的決定下一步的走向,不斷規劃下面的方向然後得到所想要的解;
    如本題首先我們可以把第一行第一列求出來非常簡單。
    第一行就是用str1的第一個字元編輯成str2[j]所以就是i*ic
    第一列就是用str2用str[i]的所有字元編輯成str2[0]所以就是i*dc
    dp[i][j]後面的就想辦法如何用之前的轉換而來,如下圖為了方便大家看我把dp打印出來
   情況1: 以dp[3][2]來看假設已經到了3,2我們如何來進行得到這個最小代價呢,首先它的前面dp[i][j-1](j-1)是一樣的str1[0...i]組成了str2[0...j-1]
    現在需要組成str2[0...j]個字元現在得到了str2[0...j-1]然後再加一個字元也就是加上str2[j]則就編輯成了str2[0....j]遞推式就是
    dp[i][j]=dp[i][j-1]+ic

   情況2:然後就是上面組成也就是可以由dp[i-1][j]也就是我可以用str1[0...i-1]編輯成str2[0....j]
   然後再把現在的str1中的最後一個沒用到的刪除掉遞推表示式就是:dp[i][j]=dp[i-1][j]+dc
   新增和刪除編譯代價都有了那麼我們來看一下修改替換的
   替換會分兩種情況:

   情況3:dp[i][j]與dp[i-1][j-1]的關係,當str1[i]==str2[j]時也就是最後一個字元已經匹配的上,也就是他前i-1和j-1個編輯的最小代價
   就是現在dp[i][j]的代價;表示式也就是:dp[i][j]==dp[i-1][j-1](str1[i]==str2[j])

   情況4:顯而易見也就是當str1[i]!=str2[j]時也就是最後一個字元匹配不上那麼他就需要把str1[i]個替換成str2[j]
   剩下的也就是和上面的情況一樣也就是str1[0...i-1]組成str2[0...j-1]的最小代價加上最後一個替換的代價就是這種情況的總得代價
   表示式:dp[i][j]==dp[i-1][j-1]+rc(str1[i]!=str2[j])

dp:
    0 5 10 15 20
    3 0 5 10 15
    6 3 2 7 12
    9 6 5 4 9
    12 9 6 7 6
    15 12 9 6 9
    18 15 12 9 8
public class DTGH_ChengeTwoString {
    public int chengeTwoString(String str1, String str2, int ic, int dc, int rc) {
        char[] str1s = str1.toCharArray();
        char[] str2s = str2.toCharArray();
        int m = str1s.length;
        int n = str2s.length;
        int[][] dp = new int[m][n];
        for (int i = 0; i < m; i++) {
            dp[i][0] = i * dc;
        }
        for (int i = 0; i < n; i++) {
            dp[0][i] = i * ic;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                int min1 = Math.min(dp[i - 1][j] + dc, dp[i][j - 1] + ic);
                if (str1s[i] == str2s[j]) {
                    dp[i][j] = Math.min(min1, dp[i - 1][j - 1]);
                } else {
                    dp[i][j] = Math.min(min1, dp[i - 1][j - 1] + rc);
                }
            }
        }
        //輸出矩陣
        for (int i = 0; i <m ; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(dp[i][j]+" ");
            }
            System.out.println();
        }
        return dp[dp.length - 1][dp[0].length - 1];
    }

    public static void main(String[] args) {
        DTGH_ChengeTwoString a = new DTGH_ChengeTwoString();
        System.out.println(a.chengeTwoString("ab12cd3", "abcdf", 5, 3, 2));
    }
}