動態規劃(四)最長公共子序列問題

       除了揹包問題和走金字塔問題,最長公共子序列也是常見動態規劃例子,本篇文章簡單分析該問題。

       最長公共子序列問題形式如下:有兩個字符串,求出最長公共子序列的長度。示例如:

           字符串A:  a  s d  h  e  j  f

           字符串B:  a  r  s  g  k  l  g  d

       則字符串A和B的最長公共子序列爲“asd”,最大公共子序列長度爲3。最長公共子序列與最長公共子串不同的是:最長公共子序列是兩個字符串中抽取出來的出現順序相同、但不必連續的子串,最長公共子串是兩個字符串中抽取出來的出現順序相同、也要連續的子串。

       與0-1問題的解法類似,此問題分析步驟如下:

           1、用一個多維數組dp的形式來模擬計算過程,數組的初始值可以用0來填充。

           2、定義狀態。如dp[ i ][  j ],定義爲字符串A[0...i]和字符串B[0...j]的最長公共子序列長度。關於dp[ i ][ j ] 的變化過程,可以分爲兩類:

                 1>當A[ i ]和B[ j ]相等時,則兩個字符串需要公共減去共有序列,然後最長公共子序列數量+1,即dp[ i ][ j ] =   dp[ i-1 ][ j-1 ] +1。

                 2>當A[ i ]和B[ j ]不相等時,就需要將A或B的字符串減去1個元素,然後取兩者的最大值,即dp[ i ][  j ] = max(dp[ i-1 ][ j ],dp[ i ][ j-1 ])。

              當最後填滿數組dp時,dp[ A.length() ][ B.length() ]即爲所求的最長公共子序列長度。

       Java代碼如下: 

            String str1 = "asdhejf";
            String str2 = "arsgklgd";
            //構建動態規劃表
            int[ ][ ] dp = new int[str1.length() + 1][str2.length() + 1];
            //賦予動態規劃表初始值
            for (int i = 0; i <= str1.length(); i++) {
                 for (int j = 0; j <= str2.length(); j++) {
                      dp[ i ][ j ] = 0;
                  }
             }
        
             for (int i = 1; i <= str1.length(); i++) {
                 for (int j = 1; j <= str2.length(); j++) {
                    if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                         //兩個字符串中要比較的元素相等
                         dp[ i ][ j ] = dp[i - 1][j - 1] + 1;
                     } else {
                         //兩個字符串中要比較的元素不相等,分別在兩個字符串中減去一元素,取較大值
                         dp[ i ][ j ] = Math.max(dp[i - 1][j],dp[i][j - 1]);
                    }
                }
            }

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