370最長公共子串和子序列 之動態規劃 求解

轉載:動態規劃之公共串

概念:

動態規劃(Dynamic programming,簡稱DP),是大家都覺得比較難以掌握的算法。爲了應付面試,我們經常會背誦一下斐波那楔數列或者揹包問題的源碼,其實,只要理解了思想,掌握基本的模型,然後再來點寫代碼的套路,動態規劃並沒有那麼難。

首先,動態規劃最重要的是掌握他的思想,動態規劃的核心思想是把原問題分解成子問題進行求解,也就是分治的思想。

經典模型

1.線性模型

最經典的問題就是斐波那楔數列的問題,每個數的值都是一個狀態,可以用F[i]表示表示第i個數的值是多少。每個數都是由F[i-1]+F[i-2]轉移而來。

另外一個經典的問題就是最長上升自序列(LIS),有一串序列,要求找出它的一串子序列,這串子序列可以不連續,但必須滿足它是嚴格的單調遞増的且爲最長的。把這個長度輸出。示例:1 7 3 5 9 4 8 結果爲4。

我們非常容易表示他的狀態,我們用f[i]表示以第i個數結尾的,最大的上升自序列是多少?那麼它是怎麼轉移的呢?非常容易想到肯定是從左邊的的數轉移而來,能轉移的數滿足什麼條件呢?肯定是比a[i]更小的。

線性模式還可以拓展成二維問題,例如揹包問題,用f[i][j]表示前i個物品,湊成大小爲j的揹包,最大的價值是多少。

這類問題非常的多,但是思路都是這樣,無非就是從左往右,從上到下,從低維到高維進行轉移。
2.區間模型
3.樹狀模型

常見案例:

1.爬樓梯

假設你正在爬樓梯。需要 n 階你才能到達樓頂。
每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是一個正整數。

class Solution {
    public int climbStairs(int n) {
        //1.特判
       if(n < 3) return n;
        //2.邊界
        int[] dp = new int[n+1]; //樓梯:1-n
        dp[1] = 1;
        dp[2] = 2;
        //3.狀態轉移方程
        for(int i = 3;i <= n;i++){
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
    }
}

最長公共子串遞推公式:(連續)
遞推公式:

1    if(s1.charAt(i) == s2.charAr(j))
2        dp[i][j] = dp[i-1][j-1] + 1;
3    else
4        dp[i][j] = 0;
 1public static int maxLong(String str1, String str2) {
 2    if (str1 == null || str2 == null || str1.length() == 0 || str2.length() == 0)
 3        return 0;
 4    int max = 0;
 5    int[] dp = new int[str2.length() + 1];
 6    for (int i = 1; i <= str1.length(); i++) {
 7        for (int j = str2.length(); j >= 1; j--) {
 8            if (str1.charAt(i - 1) == str2.charAt(j - 1))
 9                dp[j] = dp[j - 1] + 1;
10            else
11                dp[j] = 0;
12            max = Math.max(max, dp[j]);
13        }
14        Util.printIntArrays(dp);//這一行和下面一行是打印測試數據的,也可以去掉
15        System.out.println();
16    }
17    return max;
18}

子序列:(不連續)

1    if(s1.charAt(i) == s2.charAr(j))
2        dp[i][j] = dp[i-1][j-1] + 1;
3    else
4        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章