最長公共子串行(LCS)

2021-06-20 13:20:22 字數 1631 閱讀 9371

首先要明確的是子串行的概念,注意啦,子串行不等於子串。子串行是乙個字串s去掉零個或者多個字元後所剩下的字串就叫做子串行。

最長公共子串行的意思就是尋找兩個給定字串的的子串行,該子串行在兩個字串中以相同的次序出現,但是不一定是連續的。(連續的那是子串)

例如序列x=abcbdab,y=bdcaba。序列bca是x和y的乙個公共子串行,但是不是x和y的最長公共子串行,子串行bcba是x和y的乙個lcs,序列bdab也是。

最簡單想到的

尋找lcs的一種方法是列舉x所有的子串行,然後逐一檢查是否是y的子串行,並隨時記錄發現的最長子序列。假設x有m個元素,則x有2^m個子序列,指數級的時間,對長序列不實際。

其實最長公共子串行是動態規劃(dp)的典型例子。

設x=1,x2,…,xm>和y=1,y2,…,yn>為兩個字串,lcs(x,y)表示x和y的乙個最長公共子串行,可以看出

如果xm=yn,則lcs ( x,y ) =xm

+ lcs( xm-1,yn-1 

)。如果xm!=yn,則lcs( x,y )= max

lcs問題也具有重疊子問題性質:為找出x和y的乙個lcs,可能需要找x和yn-1的乙個lcs以及xm-1和y的乙個lcs。但這兩個子問題都包含著找xm-1和yn-1的乙個lcs,等等.

dp最終處理的還是數值(極值做最優解),找到了最優值,就找到了最優方案;為了找到最長的lcs,我們定義dp[i][j]記錄序列lcs的長度,合法狀態的初始值為當序列x的長度為0或y的長度為0,公共子串行lcs長度為0,即dp[i][j]=0,所以用i和j分別表示序列x的長度和序列y的長度,狀態轉移方程為

dp[i][j] = 0  如果i=0或j=0

dp[i][j] = dp[i-1][j-1] + 1 如果x[i-1] = y[i-1] (x[i-1]就是x陣列中的第i個)

dp[i][j] = max  如果x[i-1] != y[i-1]

#include using namespace std;

/* lcs

* 設序列長度都不超過20*/

int dp[21][21]; /* 儲存lcs長度, 下標i,j表示序列x,y長度 */

char x[21];

char y[21];

int i, j;

void main()

else if(dp[i][j-1] > dp[i-1][j])

else}}

printf("len of lcs is: %d\n", dp[xlen][ylen]);

/* 輸出lcs 本來是逆序列印的,可以寫一遞迴函式完成正序列印

這裡採用的方法是將y作為臨時儲存lcs的陣列,最後輸出y

*/i = xlen;

j = ylen;

int k = dp[i][j];

char lcs[21] = ;

while(i && j)

else if(x[i-1] != y[j-1] && dp[i-1][j] > dp[i][j-1])

else

}printf("%s\n",lcs);

}

例題:uva 111

**:

LCS 最長公共子串行

問題描述 我們稱序列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最長公共子串行

求兩個字串的最大公共子串行問題 子串行的定義 若給定序列x 則另一串行z 是x的子串行是指存在乙個嚴格遞增下標序列使得對於所有j 1,2,k有 zj xij。例如,序列z 是序列x 的子序列,相應的遞增下標序列為。分析 用動態規劃做 1.最長公共子串行的結構 事實上,最長公共子串行問題具有最優子結構...

LCS最長公共子串行

lcs是longest common subsequence的縮寫,即最長公共子串行。乙個序列,如果是兩個或多個已知序列的子串行,且是所有子串行中最長的,則為最長公共子串行。複雜度對於一般的lcs問題,都屬於np問題。當數列的量為一定的時,都可以採用動態規劃去解決。解法動態規劃的乙個計算最長公共子串...