动态规划——最长公共子序列与最长公共子串 (含Python实现代码)


动态规划——最长公共子序列与最长公共子串 (含Python实现代码)

  • 英文名称:

    • 最长公共子序列 Longest Common Subsequence
    • 最长公共子串 Longest Common Substring
  • 主要区别:子串必须要连续,子序列不需要

    • 举例: a b c d e f b 和 a b c x y b z
      • 最长公共子序列:a b c b
      • 最长公共子串:a b c

最长公共子序列

  • 相关符号:字符串 X 与 Y。Xi 表示X在第i位上的字符(在这里X的第一位表示为1而不是0),Yj 同理。
    c[i][j]表示字符串X1..i与Y1..j的最长公共子序列的长度
  • 递推关系式

\[ c[i][j] = \left\{ \begin{array}{} 0 & {i = 0, j = 0}\\ c[i-1][j-1] + 1 & {X_i = Y_j}\\ MAX(c[i-1][j], c[i][j-1]) & {X_i \neq Y_j}\\ \end{array} \right. \]

  • 参考代码
def longest_common_subsequence(X: str, Y: str):
    index_x = len(X)+1  # columns
    index_y = len(Y)+1  # rows
    c = [['']*index_y for _ in range(index_x)]

    for i in range(index_x):
        for j in range(index_y):
            if i == 0 or j == 0:
                c[i][j] = ''
                continue
            if X[i-1] == Y[j-1]:
                c[i][j] = c[i-1][j-1] + X[i-1]
            else:
                if len(c[i-1][j]) > len(c[i][j-1]):
                    c[i][j] = c[i-1][j]
                else:
                    c[i][j] = c[i][j-1]

    return len(c[index_x-1][index_y-1]), c[index_x-1][index_y-1]
  • 代码说明: 此处的代码在理论上做出了一些改动,二维数组c被用来存储每个位置上存在的最长序列了,
    即 c[i][j] 存储的是一个字符串而非长度。在递推关系式上,第二项(Xi = Yj 时) 改为 c[i-1][j-1] + Xi
    这样最后既可以得到最大的长度,也可以知道最长的序列是什么。

最长公共子串

  • 相关符号: 字符串 X 与 Y,角标i,j。意义同上。 c[i][j]表示字符串X1..i与Y1..j的匹配时的最长子串。 current_lcs 表示整个运行过程中遇到的最长子串
  • 递推关系式

\[ c[i][j] = \left\{ \begin{array}{} Null & {i = 0, j = 0 \ OR\ X_i \neq Y_i}\\ c[i-1][j-1] + X_i & {X_i = Y_j}\\ \end{array} \right. \]

  • 参考代码
def longest_common_substring(X: str, Y: str):
    index_x = len(X) + 1  # columns
    index_y = len(Y) + 1  # rows
    c = [[''] * index_y for _ in range(index_x)]
    current_lcs = ''

    for i in range(index_x):
        for j in range(index_y):
            if i == 0 or j == 0 or X[i-1] != Y[j-1]:
                c[i][j] = ''
                continue
            if X[i-1] == Y[j-1]:
                c[i][j] = c[i-1][j-1] + X[i-1]
                if len(c[i][j]) > len(current_lcs):
                    current_lcs = c[i][j]

    return len(current_lcs), current_lcs


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM