最長公共子串(連續)問題

2021-06-27 22:09:37 字數 2376 閱讀 3842

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

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

然後重新看一下這個問題,我們建立乙個比較矩陣來比較兩個字串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()  

}  注意:

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

最長公共子串(連續)問題

from 動態規劃有乙個經典問題是最長公共子串行,但是這裡的子串行不要求連續,如果要求序列是連續的,我們叫公共子串,那應該如何得到這個串呢?最簡單的方法就是依次比較,以某個串為母串,然後生成另乙個串的所有長度的子串,依次去母串中比較查詢,這裡可以採用先從最長的子串開始,減少比較次數,但是複雜度依然很...

最長公共子串(連續) 子串行(不連續)

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 求在兩個序列中同時出現的最長子序列的長度...

經典筆試題 最長公共子串(連續)問題

動態規劃有乙個經典問題是最長公共子 序列,但是這裡的子串行不要求連續,如果要求序列是連續的,我們叫公共子串,那應該如何得到這個串呢?最簡單的方法就是依次比較,以某個串為母串,然後生成另乙個串的所有長度的子串,依次去母串中比較查詢,這裡可以採用先從最長的子串開始,減少比較次數,但是複雜度依然很高!然後...