最長公共子串行(不連續)問題:乙個給定序列的子串行是在該序列中刪去若干元素後得到的序列。給定兩個序列x和y,當另一串行z既是x的子串行又是y的子串行時,稱z是序列x和y的公共子串行。最長公共子串行就是求給定兩個序列的乙個最長公共子串行。例如,x=「abcbdab」,y=「bcdb」是x的乙個子串行。
問題分析:
給定兩個序列a和b,稱序列z是a和b的公共子串行,是指z同是a和b的子串行。問題要求已知兩序列a和b的最長公共子串行。如採用列舉a的所有子串行,並一一檢查其是否又是b的子串行,並隨時記錄所發現的子串行,最終求出最長公共子串行。這種方法因耗時太多而不可取。
考慮最長公共子串行問題如何分解成子問題,設a=「a0,a1,…,am-1」,b=「b0,b1,…,bm-1」,並z=「z0,z1,…,zk-1」為它們的最長公共子串行。不難證明有以下性質:
(1) 如果am-1=bn-1,則zk-1=am-1=bn-1,且「z0,z1,…,zk-2」是「a0,a1,…,am-2」和「b0,b1,…,bn-2」的乙個最長公共子串行;
(2) 如果am-1!=bn-1,則若zk-1!=am-1,蘊涵「z0,z1,…,zk-1」是「a0,a1,…,am-2」和「b0,b1,…,bn-1」的乙個最長公共子串行;
(3) 如果am-1!=bn-1,則若zk-1!=bn-1,蘊涵「z0,z1,…,zk-1」是「a0,a1,…,am-1」和「b0,b1,…,bn-2」的乙個最長公共子串行。
這樣,在找a和b的公共子串行時,如有am-1=bn-1,則進一步解決乙個子問題,找「a0,a1,…,am-2」和「b0,b1,…,bm-2」的乙個 最長公共子串行;如果am-1!=bn-1,則要解決兩個子問題,找出「a0,a1,…,am-2」和「b0,b1,…,bn-1」的乙個最長公共子串行 和找出「a0,a1,…,am-1」和「b0,b1,…,bn-2」的乙個最長公共子串行,再取兩者中較長者作為a和b的最長公共子串行。
為了節約重複求相同子問題的時間,引入乙個陣列,不管它們是否對最終解有用,把所有子問題的解存於該陣列中,這就是動態規劃法所採用的基本方法,具體說明如下。
定義c[i][j]為序列「a0,a1,…,ai-2」和「b0,b1,…,bj-1」的最長公共子串行的長度,計算c[i][j]可遞迴地表述如下:
(1)c[i][j] = 0 如果i=0或j=0;
(2)c[i][j] = c[i-1][j-1]+1 如果i,j>0,且a[i-1] = b[j-1];
(3)c[i][j] = max 如果i,j>0,且a[i-1] != b[j-1]。
按此算式可寫出計算兩個序列的最長公共子串行的長度函式。由於c[i][j]的產生僅依賴於c[i-1][j-1]、c[i-1][j]和c[i][j-1],故可以從c[m][n]開始,跟蹤c[i][j]的產生過程,逆向構造出最長公共子串行。細節見程式。
#include #include #define n 100
char a[n], b[n], str[n];
int c[n][n];
int lcs_len(char* a, char* b, int c[n])
}return c[m][n];
}char* build_lcs(char s, char* a, char* b)
}return s;
}void main()
最長公共子串(連續) 子串行(不連續)
1 最長公共子串 計算兩個字串的最長公共子串的長度,字元不區分大小寫 假設 x 和 y 的序列如下 x 1.m y 1.n 可以看出,x 和 y 的最長公共子串為 a,s,d,f,a,s 即長度為6 2 最長公共子串行 給定兩個序列 x 1.m 和y 1.n 求在兩個序列中同時出現的最長子序列的長度...
最長公共子串行 最長連續公共子串行 最長遞增子串行
面試中除了排序問題,還會經常出現字串的子串行問題,這裡講解使用動態規劃解決三個常見的子串行問題 1 最長公共子串行問題 lcs,longest common subsequence problem 2 最長連續公共子串行問題 3 最長遞增子串行 lis,longest increment subse...
最長公共子數列(不連續)
最長公共子串行 南陽理工acm 本人覺得這是一道尤其水的動態規劃,通過二維陣列相等以及不相等兩種情況下的最優值尋找即可ac 具體一點就是if c1 i c2 j 計數陣列 a i j a i 1 j 1 1 否則 a i j max a i 1 j a i j 1 如下 include includ...