求最長公共子串行和最長公共子串

2021-08-16 01:47:55 字數 3453 閱讀 9568

輸入描述:

輸入為兩行字串(可能包含空格),長度均小於等於50。

輸出描述:  

輸出為乙個整數,表示最長公共連續子串的長度。

輸入例子:

abcde

abgde

輸出例子:

2題解:

/*例如:str1: abcde    str2: abgde

matrix = [ 1  0  0  0  0

0  1  0  0  0

0  0  0  0  0

0  0  0  1  0

0  0  0  0  1 ]

斜線上連續的1的最大個數為2,所以最長公共連續子串長度為2*/ 是每條對角線,而不只是主對角線。

參考**如下:

#include

#include

using namespace std;

int main()

;       

int  maxlen=0;

gets(str1);  

gets(str2);

for(int i=0;str1[i]!='\0';i++)      //如果兩個位置的元素相等,矩陣值為1

}      

for(int i=0;str1[i]!='\0';i++)      //依次找對角線最大連續1的個數

是兩個序列,將 x 和 y 的最長公共子串行記為lcs(x,y)

找出lcs(x,y)就是乙個最優化問題

。因為,我們需要找到x 和 y中最長的

那個公共子串行。而要找x 和 y的lcs,首先考慮x的最後乙個元素和y的最後乙個元素。

1)如果 xn=ym,即x的最後乙個元素與y的最後乙個元素相同,這說明該元素一定位於公共子串行中。因此,現在只需要找:lcs(xn-1,ym-1)

lcs(xn-1,ym-1)就是原問題的乙個

子問題。為什麼叫子問題?因為它的規模比原問題小。(小乙個元素也是小嘛....)

為什麼是最優的子問題?因為我們要找的是xn-1 和 ym-1 的最長公共子串行啊。。。最長的!!!換句話說,就是最優的那個。(這裡的最優就是最長的意思)

2)如果xn != ym,這下要麻煩一點,因為它產生了兩個

子問題:lcs(xn-1,ym) 和 lcs(xn,ym-1)

因為序列x 和 序列y 的最後乙個元素不相等嘛,那說明最後乙個元素不可能是最長公共子串行中的元素嘛。(都不相等了,怎麼公共嘛)。

lcs(xn-1,ym)表示:最長公共序列可以在(x1,x2,....x(n-1)) 和 (y1,y2,...yn)中找。

lcs(xn,ym-1)表示:最長公共序列可以在(x1,x2,....xn) 和 (y1,y2,...y(n-1))中找。

求解上面兩個子問題,得到的公共子串行誰最長,那誰就是 lcs(x,y)。用數學表示就是:

lcs=max

由於條件 1)  和  2)  考慮到了所有可能的情況。因此,我們成功地把原問題 轉化 成了 三個規模更小的子問題。

②重疊子問題

重疊子問題是啥?就是說原問題 轉化 成子問題後,  子問題中有相同的問題。咦?我怎麼沒有發現上面的三個子問題中有相同的啊????

ok,來看看,原問題是:lcs(x,y)。子問題有 ❶lcs(xn-1,ym-1)    ❷lcs(xn-1,ym)    ❸lcs(xn,ym-1)

初一看,這三個子問題是不重疊的。可本質上它們是重疊的,因為它們只重疊了一大部分。舉例:

第二個子問題:lcs(xn-1,ym) 就包含了:問題❶lcs(xn-1,ym-1),為什麼?

因為,當xn-1 和 ym 的最後乙個元素不相同時,我們又需要將lcs(xn-1,ym)進行分解:分解成:lcs(xn-1,ym-1) 和 lcs(xn-2,ym)

也就是說:在子問題的繼續分解中,有些問題是重疊的。

由於像lcs這樣的問題,它具有重疊子問題的性質,因此:用遞迴來求解就太不划算了。因為採用遞迴,它重複地求解了子問題啊。而且注意哦,所有子問題加起來的個數 可是指數級的哦。。。。

這篇文章中就演示了乙個遞迴求解重疊子問題的示例。

那麼問題來了,你說用遞迴求解,有指數級個子問題,故時間複雜度是指數級。這指數級個子問題,難道用了動態規劃,就變成多項式時間了??

呵呵噠。。。。

關鍵是採用動態規劃時,並不需要去一 一 計算那些重疊了的子問題。或者說:用了動態規劃之後,有些子問題 是通過 「查表「 直接得到的,而不是重新又計算一遍得到的。廢話少說:舉個例子吧!比如求fib數列。關於fib數列,可參考:

求fib(5),分解成了兩個子問題:fib(4) 和 fib(3),求解fib(4) 和 fib(3)時,又分解了一系列的小問題....

從圖中可以看出:根的左右子樹:fib(4) 和 fib(3)下,是有很多重疊的!!!比如,對於 fib(2),它就一共出現了三次。如果用遞迴來求解,fib(2)就會被計算三次,而用dp(dynamic programming)動態規劃,則fib(2)只會計算一次,其他兩次則是通過」查表「直接求得。而且,更關鍵的是:查詢求得該問題的解之後,就不需要再繼續去分解該問題了。而對於遞迴,是不斷地將問題分解,直到分解為 基準問題(fib(1) 或者 fib(0))

說了這麼多,還是要寫下最長公共子串行的遞迴式才完整。借用網友的一張圖吧:)

c[i,j]表示:(x1,x2....xi) 和 (y1,y2...yj) 的最長公共子串行的長度。(是長度哦,就是乙個整數嘛)。公式的具體解釋可參考《演算法導論》動態規劃章節

c++實現求最長公共子串行

#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

#define ll long long int

#define mod 1000000007

#define max(x, y) (x) > (y) ? (x) : (y)

#define mem0(a) memset(a,0,sizeof(a))

using namespace std;

int dp[5005][5005];

int main()

} cout << dp[len1][len2] << endl;

} return 0;

}

最長公共子串行 最長公共子串

1 最長公共子串行 採用動態規劃的思想,用乙個陣列dp i j 記錄a字串中i 1位置到b字串中j 1位置的最長公共子串行,若a i 1 b j 1 那麼dp i j dp i 1 j 1 1,若不相同,那麼dp i j 就是dp i 1 j 和dp i j 1 中的較大者。class lcs el...

最長公共子串行 最長公共子串

1.區別 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。2 最長公共子串 其實這是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公...

最長公共子串 最長公共子串行

子串要求連續 子串行不要求連續 之前的做法是dp求子序列 include include include using namespace std const int inf 0x3f3f3f3f const int mod 1000000007 string s1,s2 int dp 1010 10...