動態規劃:最長子序列問題

關於動態規劃中的最長子序列問題有很多優秀的解讀,在這裏推薦一位博主的關於最長子序列的文章,非常不錯,配有大量的圖片和文字解答,在這裏推薦給大家。本文章轉載自這裏

1.基本概念

首先需要科普一下,最長公共子序列(longest common sequence)和最長公共子串(longest common substring)不是一回事兒。什麼是子序列呢?即一個給定的序列的子序列,就是將給定序列中零個或多個元素去掉之後得到的結果。什麼是子串呢?給定串中任意個連續的字符組成的子序列稱爲該串的子串。給一個圖再解釋一下:

這裏寫圖片描述

如上圖,給定的字符序列: {a,b,c,d,e,f,g,h},它的子序列示例: {a,c,e,f} 即元素b,d,g,h被去掉後,保持原有的元素序列所得到的結果就是子序列。同理,{a,h},{c,d,e}等都是它的子序列。

它的字串示例:{c,d,e,f} 即連續元素c,d,e,f組成的串是給定序列的字串。同理,{a,b,c,d},{g,h}等都是它的字串。

這個問題說明白後,最長公共子序列(以下都簡稱LCS)就很好理解了。
給定序列s1={1,3,4,5,6,7,7,8},s2={3,5,7,4,8,6,7,8,2},s1和s2的相同子序列,且該子序列的長度最長,即是LCS。

s1和s2的其中一個最長公共子序列是 {3,4,6,7,8}

2.特徵分析

   解決LCS問題,需要把原問題分解成若干個子問題,所以需要刻畫LCS的特徵。

這裏寫圖片描述

    以例子(S1={1,3,4,5,6,7,7,8}和S2={3,5,7,4,8,6,7,8,2}),並結合上圖來說:
    假如S1的最後一個元素 與 S2的最後一個元素相等,那麼S1和S2的LCS就等於 {S1減去最後一個元素} 與 {S2減去最後一個元素} 的 LCS  再加上 S1和S2相等的最後一個元素。

   假如S1的最後一個元素 與 S2的最後一個元素不等(本例子就是屬於這種情況),那麼S1和S2的LCS就等於 : {S1減去最後一個元素} 與 S2 的LCS, {S2減去最後一個元素} 與 S1 的LCS 中的最大的那個序列。

   這就是所謂的用動態規劃解決最長子序列的狀態轉移方程的由來,很多文章並沒有解釋,使得很多同學不清不楚。

   我們假設dp[i][j]表示序列a中從0到i,以及序列b中從0到j這兩段序列的最長子序列。於是根據上面分析:
   if(a[i]==b[j]){
       dp[i][j] = dp[i-1][j-1]+1;
   }else
       dp[i][j] = max(dp[i][j-1],dp[i-1][j]);

計算LCS的長度

還是以s1={1,3,4,5,6,7,7,8},s2={3,5,7,4,8,6,7,8,2}爲例。

這裏寫圖片描述

結果

這裏寫圖片描述

至此,該表填完。根據性質,c[8,9] = S1 和 S2 的 LCS的長度,即爲5。

輸出最長子序列內容

上面我們只是得到了最長子序列的長度,如果要得到具體的內容,我們可以逆推回去。

我們根據遞歸公式構建了上表,我們將從最後一個元素c[8][9]倒推出S1和S2的LCS。
c[8][9] = 5,且S1[8] != S2[9],所以倒推回去,c[8][9]的值來源於c[8][8]的值(因爲c[8][8] > c[7][9])。
c[8][8] = 5, 且S1[8] = S2[8], 所以倒推回去,c[8][8]的值來源於 c[7][7]。
以此類推,如果遇到S1[i] != S2[j] ,且c[i-1][j] = c[i][j-1] 這種存在分支的情況,這裏請都選擇一個方向(之後遇到這樣的情況,也選擇相同的方向)。

第一種結果爲:

這裏寫圖片描述

這就是倒推回去的路徑,棕色方格爲相等元素,即LCS = {3,4,6,7,8},這是其中一個結果。

這裏寫圖片描述

即LCS ={3,5,7,7,8}。

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