可以注意到,子串行不要求所選的字母連續,只要求是按原次序組成就好
這是和子串的乙個區別
##最長公共子串行定義
最長公共子串行(longestcommonsequence)
簡稱為lcs,下同
直觀明了,就是兩個序列的共有的子串行中最長的乙個,
此圖里就是data這乙個單詞
#解法##1. 暴力法
首先我們想到的便是把兩個序列的所有可能的子串行列舉出來,一一進行比較.
所有乙個序列的子串行的組合有 **2
n2^n
2n**種可能,而且需要m次比較.
所以時間複雜度是o(m∗2
nm*2^n
m∗2n
),空間複雜度是o(2^n);
顯然出現了 指數形式的複雜度,這是在時間和空間上無法接受的.
##2 遞迴
對於序列a[0,n] 和a[0,m];
他們的最長自序列lcs(a,b)有三種情況
這有點不好理解,其實在開始遞迴時 ,程式並不知道誰能取得更大的字串,
所以將分別對應的兩種情況都進行遞迴直到遞迴出口,(相當於將每種情況都走完)
之後把所有的情況每次都層層返回,
每次返回都進行一次比較,總是取最大的返回值,這樣就得到了更長者
當序列為空的時候,返回0;
總結下來就是如下公式
根據這個公式很容易得出遞迴版的**
#define _crt_secure_no_warnings 1
#include
#include
char a[30]
, b[30]
;int a_len, lenb;
intlcs
(int
,int);
intmain()
intlcs
(int i,
int j)
考慮演算法的複雜度
時間複雜度在最好的情況下
例如,兩個序列相等,只需要o(n)線性時間內完成,
但若在最壞的情況下,
每進行一次遞迴,就會引發新的兩個問題,
而新的兩個問題又會引發各自新的問題,
重點是在各自的問題中會出現大量重複的問題.導致時間複雜度激增.
為o($ 2^n$)
最壞情況下的遞迴例子如圖
我們提到,用遞迴解決此問題最大乙個問題就是:
當不是最優解時總會出現重複計算的遞迴
為了解決這個問題,首先想到可以用一張表存入已計算的資料,
在計算之前先查表需要計算的資料是否存在,若不存在則再計算.
這是一種以空間複雜度換取時間複雜度的做法.
出現重複遞迴的本質是在每一次遞迴的不確定性,當末序列不相同時,是向右走還是向上走是未知的.如何具體確定路徑呢?
我們可以從頭開始畫一張表
每個方塊代表問題的解
從左往右,從上到下一次將這張表填滿.規則如下
當然會出現多解和歧**的情況,但不在本問題討論之內.
這張表就表示了所有可能出現的情況,從左上角或者右下角開始進行推到,很容易得到正確的結果.而且不會重複計算
以從右下角為例
總能取出乙個最長子序列bcba
下面是**
#define _crt_secure_no_warnings 1
#include
#include
char a[
500]
, b[
500]
;char num[
501]
[501];
///記錄中間結果的陣列
char flag[
501]
[501];
///標記陣列,用於標識下標的走向,構造出公共子串行
void
lcs();
///動態規劃求解
void
getlcs()
;///採用倒推方式求最長公共子串行
intmain()
void
lcs(
)else
if(num[i]
[j -1]
>num[i -1]
[j])
else}}
}void
getlcs()
else
if(flag[i]
[j]==2)
///如果是向左標記
j--;else
if(flag[i]
[j]==3)
///如果是向上標記
i--;}
for(i = k -
1; i >=
0; i--
)printf
("%c"
, res[i]);
}
參考:
1.資料結構mooc ppt
2.
動態規劃 最長公共子串行問題
最長公共子串行問題 longest common subsequence problem 簡稱lcs問題。題目為給定兩個序列x y求它們的lcs 最長公共子串行 這裡的子串行z的定義為 z中的元素既在x中也在y中,並且他們在x y中滿足嚴格的下標為乙個增序列 假設下標從左到右依次增大 另外,不要求z...
最長公共子串行問題 動態規劃
給定兩個字串s1s2.sn和t1t2.tn。求出這兩個字串最長的公共子串行 輸入 abcicba abdkscab 輸出 abca 定義dp i j 為s1 si和t1 tj對應的lcs的長度 s1 si 1和t1 tj 1對應的公共子列有三種情況 當si 1 tj 1時,在s1 si和t1 tj的...
最長公共子串行問題(動態規劃)
time limit 1000ms memory limit 65536kb problem description 給定兩個序列x input 輸入資料有多組,每組有兩行 每行為乙個長度不超過500的字串 輸入全是大寫英文本母 a,z 表示序列x和y。output 每組輸出一行,表示所求得的最長公...