Skip to content
本站總訪問量
本站訪客數 人次

最長共同子序列

1. (每次都超時,但要懂原理)遞歸方法

使用遞歸解決LCS問題,但效率較低。可以使用記憶化遞歸來提高效率。

python
def recursive_LCS(X, Y, m, n):
    if m == 0 or n == 0:
        return 0
    if X[m - 1] == Y[n - 1]:
        return 1 + recursive_LCS(X, Y, m - 1, n - 1)
    else:
        return max(recursive_LCS(X, Y, m, n - 1), recursive_LCS(X, Y, m - 1, n))

2. 動態規劃方法

使用動態規劃解決LCS問題,通常使用二維數組。 求長度

python
dp = [[0] * (n + 1) for _ in range(m + 1)]

max_length = 0  # 記錄最長共同子字串的長度

# 填充 DP 表格
for i in range(1, m + 1):
    for j in range(1, n + 1):
        if str1[i-1] == str2[j-1]:
            # 字符相同,延續之前的子字串
            dp[i][j] = dp[i-1][j-1] + 1
            max_length = max(max_length, dp[i][j])
        else:
            # 字符不同,子字串中斷
            dp[i][j] = 0

return max_length

求字串

python
def LCS_char(char, char2):
    m = len(char)
    n = len(char2)
    dp = [[''] * (n+1) for _ in range(m+1)]
    for i in range(1, m+1):
        for j in range(1, n+1):
            if char[i-1] == char2[j-1]:
                dp[i][j] = dp[i-1][j-1] + char[i-1]
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1], key=lambda x: len(x))

3. 滾動數組

優化動態規劃以減少空間覆雜度。

python
def rolling_LCS(X, Y):
    m = len(X)
    n = len(Y)
    dp = [[0] * (n + 1) for _ in range(2)]
    bi = 0  # 用於滾動的變量
    for i in range(1, m + 1):
        bi = i % 2  # 切換行
        for j in range(1, n + 1):
            if X[i - 1] == Y[j - 1]:
                dp[bi][j] = dp[1 - bi][j - 1] + 1
            else:
                dp[bi][j] = max(dp[1 - bi][j], dp[bi][j - 1])
    return dp[bi][n]

4. 字符串編輯距離方法

使用編輯距離算法解決LCS問題。(最小編輯距離)

python
def MED(X, Y):
    n = len(X)
    m = len(Y)
    dp = [[i+j for j in range(m+1)] for i in range(n+1)]
    for i in range(1, n+1):
        for j in range(1, m+1):
            if X[i-1] == Y[j-1]:
                d = 0
            else:
                d = 1
            dp[i][j] = min(dp[i-1][j] + 1, dp[i][j-1] + 1, dp[i-1][j-1] + d)
    return dp[n][m]
python
X = "ABCBDAB"
Y = "BDCAB"

print("recursive_LCS:", recursive_LCS(X, Y, len(X), len(Y)))
print("LCS:", LCS(X, Y))
print("rolling_LCS:", rolling_LCS(X, Y))
print("edit_distance_LCS:", MED(X, Y))

Contributors

The avatar of contributor named as lucashsu95 lucashsu95

Changelog