求兩個已知序列的最長公共子串行,乙個序列的子串行滿足下標嚴格遞增。
如果zk 是 xi 和 yj 的最長公共子串行(下標表示該序列的長度)
則有以下三點規則:
(1) 如果x[i] = y[j],那麼z[k] = x[i] =y[j],zk-1 是 xi-1 和 yj-1 的最長公共子串行;
(2) 如果x[i] ≠ y[j],z[k] ≠ x[i] ,那麼zk 是 xi-1 和 yj 的最長公共子串行;
(3) 如果x[i] ≠ y[j],z[k] ≠ y[j] ,那麼zk 是 xi 和 yj-1 的最長公共子串行;
得出演算法遞推關係:
c[i][j]表示x序列前i個元素和y序列前j個元素的最長公共子串行長度(int), i < xlen, j < ylen
c[i][j] = c[i-1][j-1] + 1 , x[i] = y[j]
c[i][j] = max, x[i] != y[j]
c[i][j] 存放兩個序列的最長公共子串行的長度
b[i][j] 存放兩個序列與[i-1],[j-1]兩個序列的關係
stack,存放子串行的棧
初始化:c[0][j] 和c[i][0]都為0
for i < xlen
for j < ylen
if(x[i]==y[j]) c[i][j] = c[i-1][j-1] +1 b[i][j] = 『2』;
else c[i][j] = c[i-1][j] >= c[i][j-1] ? c[i-1][j] : c[i][j-1] b[i][j] =『x』 || 『y』
for i = xlen, j = ylen; i>0 && j>0
if (b[i][j] == 『x』) i–;
else if (b[i][j] == 『y』) j–;
else stack.push(x[i]) i-- j–
逐個pop stack;
t = o(xlen * ylen)
#include
#include
#include
#include
using namespace std;
#define xlen 5
#define ylen 4
void
getlcs
(char x,
char y)
for(
int j =
0; j < ylen; j++
)for
(int k =
1; k <= xlen; k++
)else
if(c[k -1]
[l]>= c[k]
[l -1]
)else}}
printf
("%d\n"
, c[xlen]
[ylen]);
for(
int i = xlen,j = ylen;j >
0&& i >0;
)}while
(!s.
empty()
)}intmain()
x[i]
= ch;
}for
(int i =1;
; i++
) y[i]
= ch;
}getlcs
(x, y)
;return0;
}
LCS問題 動態規劃
簡述 lcs問題,即最長公共子串行問題,給定兩個序列x 和y 求x y最長的公共子串行。與lis類似,lcs也是可以不連續的。解題思路 本人覺得在這個問題上演算法導論講的很好,所以在此我主要是整理。1 首先我們來考慮暴力搜尋求解的方法,我們要暴力列舉x的所有子串行,然後再看看是不是也是y的子串行,這...
動態規劃解LCS問題
今天研究了一下動態規劃,思想很簡單 循序漸進,區域性推到整體。但運用起來還是不太好想的。下面用動態規劃解lcs最大公共子串問題 寫了兩個函式lcs和lcs inhance,前者用矩陣實現 用於理解原理 後者用兩個陣列實現 節省空間 如下 include includeusing namespace ...
動態規劃之LCS演算法
lcs是longest common subsequence的縮寫,即最長公共子串行。乙個序列,如果是兩個或多個已知序列的子串行,且是所有子串行中最長的,則為最長公共子串行。另外還有個分支問題 最長公共子串。子串的字元位置必須連續,而子串行則不必,從原序列中去掉任意的元素獲得的新序列。可以看出,子串...