兩個字串(可能包含空格),找出其中最長的公共連續子串, 並輸出其長度。
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 中公共子串...