最長公共子串

2021-06-25 08:21:43 字數 2442 閱讀 4142

**實現:

public class lcs2

if(max

下文**:

動態規劃有乙個經典問題是最長公共子串行,但是這裡的子串行不要求連續,如果要求序列是連續的,我們叫公共子串,那應該如何得到這個串呢?

最簡單的方法就是依次比較,以某個串為母串,然後生成另乙個串的所有長度的子串,依次去母串中比較查詢,這裡可以採用先從最長的子串開始,減少比較次數,但是複雜度依然很高!

然後重新看一下這個問題,我們建立乙個比較矩陣來比較兩個字串str1和str2

定義 lcs(i,j) ,當str1[i] = str2[j]時lcs(i,j)=1,否則等於0。

example:

str1 = "bab"

str2 = "caba"

建立矩陣

--b  a  b

c0  0  0

a0  1  0

b1  0  1

a0  1  0

連續i子串的特點就是如果str1[i]和str2[j]是屬於某公共子串的最後乙個字元,那麼一定有str1[i]=str2[j] && str1[i-1] = str2[j-1],從矩陣中直觀的看,就是由「1」構成的「斜線」代表的序列都是公共子串,那麼最長公共子串肯定就是斜線「1」最長的那個串。

那麼現在問題就可以轉化了,只要構造出如上的乙個矩陣,用n^2的時間就可以得到矩陣,然後再到矩陣中去尋找最長的那個「1」構成的斜線就可以了!那麼,現在又有了新的問題?如何快速的找到那個「1」構成的最長斜線呢?

採用dp的思想,如果str1[i] = str2[j],那麼此處的包含str1[i] 和 str2[j]公共子串的長度必然是包含str1[i-1]和str2[j-1]的公共子串的長度加1,那麼現在我們可以重新定義lcs(i,j),即是lcs(i,j) = lcs(i-1,j-1) + 1,反之,lcs(i,j) = 0。那麼上面的矩陣就變成了如下的樣子:

--b  a  b

c0  0  0

a0  1  0

b1  0  2

a0  2  0

現在問題又變簡單了,只需要花n^2的時間構造這樣乙個矩陣,再花n^2的時間去找到矩陣中最大的那個值,對應的就是最長公共子串的長度,而最大值對應的位置對應的字元,就是最長公共子串的最末字元。

演算法還可以改進,我們可以將查詢最大長度和對應字元的工作放在構造矩陣的過程中完成,一邊構造一邊記錄當前的最大長度和對應位置,這樣就節省了n^2的查詢時間。

空間上也可以做改進,如果按照如上的方式構造,我們發現,當矩陣的第i+1行的值計算完成後,第i行的值就沒有用了,即便是最長的長度出現在第i行,我們也已經用變數記錄下來了。因此,可以將矩陣縮減成乙個向量來處理,向量的當前值對應第i行,向量的下乙個迴圈後的值對應第i+1行。

**如下:

[cpp]view plain

copy

//  最長公共子串(連續)  lcs

//  deng chao

//  2012.12.4

#include 

#include 

using

namespace

std;  

//  查詢公共子串

//  lcs記錄公共子串

//  return  公共子串長度

intlcs(

const

char

*str1  , 

intlen1 , 

const

char

*str2 , 

intlen2 , 

char

*&lcs)  

//  壓縮後的最長子串記錄向量

int*c = 

newint

[len2+1];  

for(

inti = 0 ; i < len2 ; ++i)  

intmax_len = 0;    

//匹配的長度

intpos = 0;        

//在str2上的匹配最末位置

for(

inti = 0 ; i < len1 ; ++i)  

}  else

}  }  if

(0 == max_len)  

//  得到公共子串

lcs = new

char

[max_len];  

for(

inti = 0 ; i < max_len ; ++i)  

cout<<"pos = "

<

delete

c;  

delete

lcs;  

return

max_len;  

}  //  test

intmain()  

}  注意:

在更新最長子串長度的向量時,是從後往前遍歷更新的,為什麼???從前往後遍歷更新會出現什麼情況?

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

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...