最長的公共連續子串

2021-10-24 11:58:02 字數 3421 閱讀 8275

兩個字串(可能包含空格),找出其中最長的公共連續子串, 並輸出其長度。

2.1 動態規劃(二維)

建立乙個二維陣列 dp[

n][m

]dp[n][m]

dp[n][

m],其中 dp[

i][j

]dp[i][j]

dp[i][

j]: 表示取到 s1[

i]

s1[i]

s1[i

] 和取到 s2[

j]

s2[j]

s2[j

] 時的最大連續子串長度。

如果 s1[

i]

s1[i]

s1[i

] 等於 s2[

j]

s2[j]

s2[j

],則 dp[

i][j

]dp[i][j]

dp[i][

j]等於取到 s1[

i−1]

s1[i-1]

s1[i−1

] 和取到 s2[

j−1]

s2[j-1]

s2[j−1

] 時的最大連續子串長度加 1

11,即 :

d p[

i][j

]=dp

[i−1

][j−

1]+1

dp[i][j]=dp[i-1][j-1]+1

dp[i][

j]=d

p[i−

1][j

−1]+

1

import sys

defmaxsubstr

(s1, s2)

: n1 =

len(s1)

n2 =

len(s2)

maxlen =

0 maxend_1 =

0 maxend_2 =

0 dp =[[

0]* n2 for i in

range

(n1)

]for i in

range

(n1)

:for j in

range

(n2)

:if s1[i]

== s2[j]:if

(i ==

0or j ==0)

: dp[i]

[j]=

1else

: dp[i]

[j]= dp[i -1]

[j -1]

+1else

: dp[i]

[j]=

0# 為了後續取出子串

if dp[i]

[j]> maxlen:

maxlen = dp[i]

[j] maxend_1 = i # 字串 s1 的終點位置

maxend_2 = j # 字串 s2 的終點位置

return maxlen, s1[maxend_1 - maxlen +

1: maxend_1+1]

, s2[maxend_2 - maxlen +

1: maxend_2+1]

if __name__ ==

'__main__'

: s1 =

's wwabc2asssssabca'

s2 =

'wqabc2a'

# s1 = sys.stdin.readline().strip()

# s2 = sys.stdin.readline().strip()

res = maxsubstr(s1, s2)

print

(res)

輸出:

(長度,從 s1 中擷取的, 從 s2 中擷取的)

(5, 'abc2a', 'abc2a')
2.2 動態規劃( o(1

)o(1)

o(1)

優化:每次計算 dp[

i][j

]dp[i][j]

dp[i][

j]的時候,最多隻需要其左上方的 dp[

i−1]

[j−1

]dp[i-1][j-1]

dp[i−1

][j−

1]的值,所以按照斜線方向(自左上角 至 右下角 方向)來計算所有的值

def

maxsubstr_2

(s1, s2)

: n1 =

len(s1)

n2 =

len(s2)

row =

0# 斜線開始位置的行

col = n2 -

1# 斜線開始位置的列

maxlen =

0# 最大長度

end =

0# 子串的結尾位置索引

while row < n1:

i = row

j = col

curlen =

0while i < n1 and j < n2:

# 從 (i, j) 開始向右下方遍歷

if s1[i]

!= s2[j]

: curlen =

0else

: curlen +=

1if curlen > maxlen:

# 記錄最大值,以及結束字元的位置索引

end = i

maxlen = curlen

i +=

1 j +=

1if col >0:

# 斜線開始位置的列先向左移動

col -=

1else

:# 列移動到最左之後,行向下移動

row +=

1return maxlen, s1[end - maxlen +

1: end +1]

if __name__ ==

'__main__'

: s1 =

's wwabsedc2asssssabca'

s2 =

'wqabesdc2a'

# s2 = 'dddd'

res2 = maxsubstr_2(s1, s2)

print

("res2:"

, res2)

輸出:

res2: (4, 'dc2a')
參考:

動態規劃-----最長公共連續子串

最長公共連續子串和最長連續公共子串行

用二維陣列c i j 記錄串x1 x2 x i x1x2 xi與y 1y 2 y j y1y2 yj 的lcs長度,則可得到狀態轉移方程c i,j 0c i 1 j 1 1max c i,j 1 c i 1,j i 0 orj 0i,j 0a ndxi y j i,j 0a ndxi y j pub...

求最長連續公共子串

說到求最長公共子串首先想到的是逐個子串比較,但是那樣的話演算法的複雜度太高,後來就想到用矩陣的方法去解決 思路如下 比如字元創a abcdefg 和字串b bdeabc 建立矩陣如下圖所示 發現如果連續的斜線值為1的長度最長的話 則為最長公共子串 則abc為最長公共子串 那我們可把矩陣進化為 我們在...

最長公共連續子串

這是兩個字串,所以狀態轉移矩陣肯定是二維矩陣。另外dp i j 代表的意思不是分別乙個字串的前 i 個和另乙個字串的前 j 個字元裡面的最長連續子串。而是以a i 和b j 為末端的公共連續子串長度。如果dp i j 代表是目前最長連續子串,那麼遞推公式就寫不出來,因為不知道dp i j 中公共子串...