動態規劃 最長公共子串行

2021-10-05 23:06:27 字數 2373 閱讀 1844

設計與實現最長公共子串行問題的演算法;

首先需要明確子串行的概念,子串行與子串並不是一種東西,子串行我們可以理解為在乙個序列中刪除任意多個字元,剩餘字元按原有順序組成的序列就是原序列的子串行,其中刪除的字元可以使連續的也可以是不連續的,對於任意乙個字元來說,有刪除與不刪除兩種選擇,那麼對於乙個長為n的序列,他就有2^n個子序列。

我們想求兩個序列的最長公共子串行,最簡單的方法就是生成乙個序列的所有子串行,然後檢查這些子串行是否是另乙個序列的子串行,並找到最長的公共子串行。這個方法其中的難點在於如何生成乙個序列的所有子串行,方法一時利用二進位制掩碼來決定序列的某一位是否應該刪除,然而這種方法涉及到了移位運算,int型變數有32位,因此當序列長度超過32時就會出錯,即使換成long也只有64位,因此這種方法侷限性很大。

另一種可以產生所有子串行的方法就是深度優先搜尋,我們可以將母序列想象成乙個迷宮,每乙個字元都是迷宮的路徑,而選擇留下該字元和不留下該字元就是路徑的兩條分叉路,而已經遍歷到了母序列的終點就是迷宮的死路,當已經遍歷到死路時就回溯到上一層就,直至回到起點就可以得到所有子串行。這樣的方法雖然可以克服掩碼的確定,然而總共有2^n個子序列,因此無論子串行與另乙個序列的比較過程有多簡潔,它的時間複雜度也是指數級的,因此該方法我們了解了就好,不應當在我們的考慮範圍內。

那麼如何使用動態規劃來解決這個問題呢?我們記兩個序列分別為x=、y=,他們的乙個公共子串行為z=,z中的所有元素必定是xy共有的, 但是位置是不確定的,我們可以由此得到如下結論:

①若xm = yn,則zk = xm = yn,那麼zk-1為xm-1和yn-1的公共子串行

②若xm != yn,且zk != xm,那麼z是xm-1和y的公共子串行

③若xm != yn,且zk != yn,那麼z是x和yn-1的公共子串行

根據以上結論,我們可以用c[i][j]來表示x的前i個字元與y的前j個字元的最長公共子串行的長度,我們可以得到以下遞推公式:

但是這樣我們只能得到最長公共子串行的長度,如果我們希望得到最長公共子串行,我們還需要增加乙個追蹤函式b[i][j],遞推公式和c[i][j]類似,如下:

當我們得到最長公共子串行的長度後,就可以根據箭頭往回追蹤得到最長公共子串行

演算法一、lcs_dp

輸入:序列str1=,序列str2=

①for i=0 to m c[i][0]=0

②for j=0 to n c[0][j]=0

③for i = 1 to m

④ for j = 1 to n

⑤ if str1[i-1]==str[j-1] then c[i][j] = c[i-1][j-1]+1,b[i][j]=↖

⑥ else if c[i-1][j] >= c[i][j-1] then c[i][j] = c[i-1][j],b[i][j]=↑

⑦ else c[i][j] = c[i][j-1],b[i][j]=←

⑧return c[m][n]

演算法二、return_res(用於返回最長子序列)

輸入:序列str1=,序列str2=,追蹤矩陣b[n][m]

①i = m, j = n, res=」」

②while i>0 && j>0 do

③ if str1[i-1] == str2[j-1] then res.insert(0,str[i-1])

④ if b[i][j] == ↖ then i–,j–

⑤ else if b[i][j] == ↑ then i–

⑥ else if b[i][j] = ← then j—

⑦return res

求最長公共子串行長度,填充追蹤矩陣的**:

int lcs_dp(int n1, int n2)

else if (c[i - 1][j] >= c[i][j - 1])

else

}} return c[n1][n2];

}

得到最長公共子串行的**:

string return_res(int n1, int n2)

if (b[i][j] == 'c')i--, j--;

else if (b[i][j] == 'u')i--;

else if (b[i][j] == 'l')j--;

} return res;

}

動態規劃演算法巢狀了兩層迴圈,外層迴圈次數取決於序列1的長度n1,而內層迴圈的次數取決於序列2的長度n2,因此演算法的時間複雜度為o(n1*n2)

動態規劃 最長公共子串行

問題描述 我們稱序列z z1,z2,zk 是序列x x1,x2,xm 的子串行當且僅當存在嚴格上公升的序列 i1,i2,ik 使得對j 1,2,k,有xij zj。比如z a,b,f,c 是x a,b,c,f,b,c 的子串行。現在給出兩個序列x和y,你的任務是找到x和y的最大公共子串行,也就是說要...

動態規劃 最長公共子串行

兩個序列的最長公共子序 lcs longest common length 的 每個字元可以不連續,如x y 那麼它們的最長公共子串行為。這是乙個經典的動態規劃問題,著手點還是找到 最精髓的 狀態轉移方程 假設x,y兩個序列的前i,j個位置的最大子串行已經找到為r i j 自底往上 那麼x i 與y...

動態規劃 最長公共子串行

看完演算法導論關於這部分內容之後的總結 關於最長公共子串行問題 給定兩個子串行 x y 求x和y長度最長的公共子串行。解決方法 首先先要了解lcs的最優子結構,令x y 為兩個子串行,z 為x和y的任意lcs。1 如果 xm yn 則 zk xm yn 且 zk 1 是 xm 1 和 yn 1 的乙...