最长公共子序列(Longest Common Subsequence, LCS)

最长公共子序列(Longest Common Subsequence, LCS)问题是计算机科学中的经典问题,用于寻找两个或多个序列(通常是字符串)中最长的相同子序列,但子序列中的元素不一定在原序列中保持原有的连续性。简单来说,就是找出一个子序列,它既存在于序列A中,又存在于序列B中,且长度最长。LCS问题在文本编辑、生物信息学等领域有广泛应用。

基本概念:

  • 子序列:一个序列可以通过删除原序列中某些元素(也可以不删除)得到,但不能改变元素之间的相对顺序。例如,对于序列 "ABCDEF",其子序列包括 "A", "AB", "ABC", "AD", "B", "BC", "C", ..., "DEF", "F" 等。

最长公共子序列(LCS):给定两个序列 X=x1​,x2​,...,xm​ 和Y=y1​,y2​,...,yn​,它们的最长公共子序列 Z=z1​,z2​,...,zk​ 是满足以下条件的最长子序列:

  1. Z 是 X 的子序列。
  2. Z 是 Y 的子序列。

动态规划解法: LCS问题可以使用动态规划方法有效解决。定义一个二维数组 Lij 表示序列X1..i 和序列Y1..j 的最长公共子序列的长度。状态转移方程如下:

L\[i\]\[j\] = \\begin{cases} L\[i-1\]\[j-1\] + 1, \& \\text{如果 } x_i = y_j \\ \\max(L\[i-1\]\[j\], L\[i\]\[j-1\]), \& \\text{如果 } x_i \\neq y_j \\end{cases}

解释:当 xi​ 与 yj​ 相等时,最长公共子序列可以通过在前一个状态 Li−1j−1 的基础上增加一个字符得到;否则,最长公共子序列可能来自 X1..i−1 与 Y1..j 的最长公共子序列,也可能来自 X1..i 与 Y1..j−1 的最长公共子序列,取两者中的较大值。

初始化状态:0=0L0j=Li0=0,表示一个空序列与任何序列的最长公共子序列长度为0。

最终答案即 Lmn,表示整个序列 X 和序列 Y 的最长公共子序列的长度。

如果需要找出具体的最长公共子序列,可以使用一个额外的二维数组 Pij 存储决策信息,记录 Lij 是通过哪个状态转移得到的。回溯 P 数组即可重构最长公共子序列。

以下是使用动态规划解决最长公共子序列问题的Python示例:

复制代码
 

Python

复制代码
1def longest_common_subsequence(X, Y):
2    m, n = len(X), len(Y)
3    L = [[0] * (n + 1) for _ in range(m + 1)]
4
5    for i in range(1, m + 1):
6        for j in range(1, n + 1):
7            if X[i - 1] == Y[j - 1]:
8                L[i][j] = L[i - 1][j - 1] + 1
9            else:
10                L[i][j] = max(L[i - 1][j], L[i][j - 1])
11
12    return L[m][n]
13
14# 示例
15X = "ABCBDAB"
16Y = "BDCAB"
17
18lcs_length = longest_common_subsequence(X, Y)
19print("最长公共子序列长度:", lcs_length)

定义了一个名为longest_common_subsequence的函数,它接受两个字符串 X 和 Y 作为参数,返回它们的最长公共子序列的长度。在代码中,动态规划表 L 的大小为 (m+1) x (n+1),其中 m 和 n 分别是字符串 X 和 Y 的长度。通过双重循环计算出每一项 L[i][j] 的值,最后返回 L[m][n] 即为所求的最长公共子序列长度。

相关推荐
高级程序源几秒前
springboot大学生体测系统72170-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·python·django·课程设计
打工仔折腾 AI13 分钟前
极空间用 Docker 部署 Photopea:网页版 PS 的私有化实践
运维·后端·python·docker·容器·langchain·ai agent 实战
Eiceblue22 分钟前
使用 Python 实现 Excel 行列转置(保留单元格样式)
前端·python·excel
念越23 分钟前
题库、练习与错题本代码阅读
开发语言·数据结构
WeiXin_DZbishe23 分钟前
基于Node.js的马拉松赛事管理系统的设计与实现-计算机毕设 附源码【课程设计】90211
java·javascript·vue.js·python·php·课程设计
zhenaibo52128 分钟前
如何与导师有效沟通选题?
算法
熊猫钓鱼>_>34 分钟前
大学图论第 6 讲:网络流与二分图匹配——对偶性让瓶颈自己现形
开发语言·算法·面试·职场和发展·图论·校招·面经
计算机编程指导师38 分钟前
计算机毕设选题推荐:基于Spark+Django的黄金价格历史数据分析与可视化系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·python·计算机·spark·django·课程设计·黄金价格
没有钱的钱仔40 分钟前
最大似然估计(MLE)通俗理解
算法·机器学习·概率论
yi0111 小时前
LeetCode 424. 替换后的最长重复字符|不定长滑动窗口:如何判断窗口是否合法?
笔记·python·算法·leetcode·双指针·滑动窗口