☆☆☆最长公共子串与最长公共子序列

131 阅读1分钟

1. 题目背景

最长公共子串(Longest Common Substring)与最长公共子序列(Longest Common Subsequence)的区别: 子串要求在原字符串中是连续的,而子序列则只需保持相对顺序,并不要求连续。

2. 最长公共子串

给出两个字符串 a 和 b 的最长连续公共子串的长度。 例如 "abcbcde" 和 "bbcbce" 的最长连续公共子串是 "bcbc" ,长度为 4

image.png

  • 核心代码:
def lcs_str(m, n):
    ml = len(m)
    nl = len(n)
    dp = [[0] * nl for _ in range(ml)]
    mmax = 0
    m_end = 0
    for i in range(ml):
        for j in range(nl):
            if m[i] == n[j]:
                if i > 0 and j > 0:
                    dp[i][j] = dp[i - 1][j - 1] + 1
                else:
                    dp[i][j] = 1
            else:
                dp[i][j] = 0
            if dp[i][j] > mmax:
                mmax = dp[i][j]
                m_end = i + 1
    return m[m_end - mmax:m_end], mmax

3. 最长公共子序列

给出两个字符串 a 和 b 的最长公共子序列的长度。和公共子串的不同是,公共子序列不要求连续。 例如 "abcbcde" 和 "acabdef" 的最长公共子序列是 "acbde" ,长度为 5 。

image.png

  • 核心代码:
def lcs_sub(text1, text2):
    ml = len(text1)
    nl = len(text2)
    dp = [[0] * nl for _ in range(ml)]
    mmax = 0
    for i in range(ml):
        for j in range(nl):
            if text1[i] == text2[j]:
                if i > 0 and j > 0:
                    dp[i][j] = dp[i - 1][j - 1] + 1
                else:
                    dp[i][j] = 1
            else:
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
            if dp[i][j] > mmax:
                mmax = dp[i][j]
    return mmax