動態規劃 最長公共子串行

2021-10-04 06:46:02 字數 1383 閱讀 5346

最長公共子串行(longest common subsequence)的問題描述為:

給定兩個字串a和b,求乙個字串,使得這個字串是 a 和 b 的最長公共部分

例如:「sadstory」 和 「adminsorry」 的最長公共子串行為 「adsory」,長度為 6

如果是暴力解法遍歷的話……設a和b的長度分別是 n 和 m,對於兩個字串的子串行各有 2n, 2m,然後再比較是否相同又需要 o(max(m,n)) ,這樣總複雜度就會達到o(2m+n x max(m, n))。

還是讓我們來看看動態規劃的做法。

我們使用乙個陣列dp[i][j],表示字串 a 的 i 號位和字串 b 的 j 號位之前的 lcs 長度(下標從 1 開始),如dp[4][5]代表 「sads」 和 「admin」 的lcs長度,那麼可以根據 a[i] 和 b[j] 的情況,分為兩種情況:

由此可以得到狀態轉移方程:

if(a[i] == b[j]) dp[i][j] = dp[i-1][j-1]

if(a[i] != b[j]) dp[i][j] = max(dp[i-1][j], dp[i][j-1])

其中,如果某乙個字串的長度為 0,那麼 lcs 一定為 0,所以有邊界:

dp[i][0] = dp[0][j] = 0

這樣狀態dp[i][j],只與其之前的狀態有關,由邊界出發就可以得到整個 dp 陣列,最終dp[n][m]就是需要的答案,時間複雜度為 o(mn)。

**實現如下:

#include

#include

#include

using

namespace std;

const

int n =

100;

char a[n]

, b[n]

;// 存放字串

int dp[n]

[n];

intmain()

for(

int i =

0; i <= lenb; i++

)// 狀態轉移方程

for(

int i =

1; i <= lena; i++

)else}}

// dp[lena][lenb]就是答案

printf

("%d\n"

, dp[lena]

[lenb]);

return0;

}/*input:

sadstory

adminsorry

output:

6 */

動態規劃 最長公共子串行

問題描述 我們稱序列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 的乙...