最長共同字串
最長共同子串(Longest Common Substring)問題是在兩串或多串字串中找出最長的共同子串。例如,對於字串 "ABCDAB" 和 "ABCDBA",它們的最長共同子串是 "ABCD"。
這個問題可以用動態規劃(Dynamic Programming)來解決。我們可以定義一個二維數組 lcs[i][j],其中 i 和 j 分別表示字串 A 和 B 的下標,lcs[i][j] 表示字串 A 的第 i 個字元到字串 B 的第 j 個字元的最長共同子串長度。
可以使用以下遞推公式來計算 lcs[i][j]:
lcs[i][j] = 最大(lcs[i-1][j-1] + 1 if A[i] == B[j] else 0, lcs[i][j-1], lcs[i-1][j])
這裡的 +1 表示如果 A[i] == B[j],則當前字元也匹配,所以最長共同子串的長度增加 1。如果 A[i] != B[j],則當前字元不匹配,我們取 lcs[i-1][j-1]、lcs[i][j-1] 和 lcs[i-1][j] 三者中的最大值,這三個值分別表示:
- lcs[i-1][j-1] + 1:如果 A[i] == B[j],則最長共同子串的長度增加 1。
- lcs[i][j-1]:如果 A[i] != B[j],則考慮不包含 A[i] 的最長共同子串。
- lcs[i-1][j]:如果 A[i] != B[j],則考慮不包含 B[j] 的最長共同子串。
最後,最長共同子串的長度就是 lcs[n][m],其中 n 和 m 分別是字串 A 和 B 的長度。
以下是一個簡單的 Python 實現:
def lcs(str1, str2):
n, m = len(str1), len(str2)
lcs_length = [[0 for _ in range(m + 1)] for _ in range(n + 1)]
for i in range(n):
for j in range(m):
if str1[i] == str2[j]:
lcs_length[i + 1][j + 1] = lcs_length[i][j] + 1
else:
lcs_length[i + 1][j + 1] = max(lcs_length[i + 1][j], lcs_length[i][j + 1], lcs_length[i][j])
return lcs_length[n][m]
str1 = "ABCDAB"
str2 = "ABCDBA"
print(lcs(str1, str2))
這個算法的時間複雜度為 O(mn),其中 m 和 n 分別是兩串字串的長度。空間複雜度為 O(mn),因為我們使用了二維數組 lcs_length。如果字串較長,可以使用一些優化技巧,比如使用二維哈希表來加速比較過程。