📜  打印最长公共子序列(1)

📅  最后修改于: 2023-12-03 15:25:46.217000             🧑  作者: Mango

打印最长公共子序列

最长公共子序列(Longest Common Subsequence,LCS)是一道经典的算法问题,用来求解两个序列的最长子序列的长度。最长子序列不要求连续,但是需要保证顺序一致。例如字符串 "abcde" 和 "ace" 的最长公共子序列是 "ace"。

这里我们将介绍如何打印最长公共子序列的具体方法,并提供代码示例。

暴力枚举法

暴力枚举法是最朴素的求解方法,它采用两重循环依次枚举两个序列所有的共同子序列,然后返回最长的那个子序列即可。

时间复杂度为 $O(2^n)$,效率较低,不建议实际应用。

def longestCommonSubsequence(s1, s2):
    """
    暴力枚举法
    """
    def dfs(i, j):
        if i == len(s1) or j == len(s2):
            return []
        if s1[i] == s2[j]:
            return [s1[i]] + dfs(i+1, j+1)
        else:
            return max(dfs(i+1, j), dfs(i, j+1), key=len)
    return dfs(0, 0)

s1 = "abcde"
s2 = "ace"
print(longestCommonSubsequence(s1, s2))  # 输出: ['a', 'c', 'e']

动态规划法

动态规划是求解最长公共子序列问题的经典方法,它将问题划分为若干个子问题,并将子问题之间的关系表示为状态转移方程式,从而得到最长公共子序列的长度。

时间复杂度为 $O(mn)$,其中 m 和 n 分别是两个序列的长度。

def printLCS(s1, s2):
    """
    动态规划法
    """
    m, n = len(s1), len(s2)
    dp = [["" for _ in range(n+1)] for _ in range(m+1)]
    for i in range(1, m+1):
        for j in range(1, n+1):
            if s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1] + s1[i-1]
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1], key=len)
    return dp[m][n]

s1 = "abcde"
s2 = "ace"
print(printLCS(s1, s2))  # 输出: ace

以上即为打印最长公共子序列的两种实现方式,使用动态规划的方法更为高效,可以在实际应用中使用。