[算法] 动态规划算法解最长公共子序列LCS问题

模拟算法: LCS

动态规划算法解最长公共子序列LCS问题

算法导论15章

不用数组:

def LCS(S1, S2, x, y):
    if (x == -1) or (y == -1):
        return 0
    if S1[x] == S2[y]:
        return 1 + LCS(S1, S2, x-1, y-1)
    return max(LCS(S1, S2, x, y-1), LCS(S1, S2, x-1, y))

print(LCS('ABCBDAB', 'BDCABA', 6, 5))

使用二维数组:

# O(mn)
def LCS_length(X, Y):
    m = len(X)
    n = len(Y)
    c = [[0 for i in range(n+1)] for i in range(m+1)]
    for i in range(m):
        for j in range(n):
            if X[i] == Y[j]:
                c[i+1][j+1] = c[i][j]+1
            else:
                c[i+1][j+1] = max(c[i+1][j], c[i][j+1])
    return c

# O(m+n)
def print_LCS(c, X, i, j):
    if i == 0 or j == 0:
        return
    if c[i][j] == c[i-1][j-1]+1:
        print_LCS(c, X, i-1, j-1)
        print(X[i-1])
    elif c[i][j] == c[i-1][j]:
        print_LCS(c, X, i-1, j)
    else:
        print_LCS(c, X, i, j-1)

X = 'ABCBDAB'
Y = 'BDCABA'
c = LCS_length(X, Y)
print('\n'.join([str(row) for row in c]))
print_LCS(c, X, len(X), len(Y))

应用场景

字符串相似度计算

LCS与GST的一个重要区别就是LCS得到的最大公共子串是严格有序的, 对于一些顺序调换的情况, 它计算出的相似度是比较低的, 相反, GST并不要求其子串严格有序, 只要存在相等子串, 即使位置不对也可找到, 因此相对来说, 它计算出的相似度更高.

在分析生物学领域, DNA分子常被表示成一个字符串, 两个DNA分子之间的相似性常用它们共同包含的碱基对的序列长度来度量, 这是最长公共子序列应用最广泛的领域, LCS还可以应用于数据压缩、文件比较、语言识别等方面. GST算法在信息检索、文本编辑、信息提取等领域有重要的应用.