【动态规划算法】【Python实现】最长公共子序列

ops/2024/9/24 20:44:18/

文章目录

问题描述

  • 给定两个序列 X = { x 1 , x 2 , ⋯ , x m } X = \set{x_{1} , x_{2} , \cdots , x_{m}} X={x1,x2,,xm} Y = { y 1 , y 2 , ⋯ , y n } Y = \set{y_{1} , y_{2} , \cdots , y_{n}} Y={y1,y2,,yn},找出 X X X Y Y Y的最长公共子序列

最长公共子序列的结构

  • 设序列 X = { x 1 , x 2 , ⋯ , x m } X = \set{x_{1} , x_{2} , \cdots , x_{m}} X={x1,x2,,xm} Y = { y 1 , y 2 , ⋯ , y n } Y = \set{y_{1} , y_{2} , \cdots , y_{n}} Y={y1,y2,,yn}的最长公共子序列为 Z = { z 1 , z 2 , ⋯ , z k } Z = \set{z_{1} , z_{2} , \cdots , z_{k}} Z={z1,z2,,zk}
    • x m = y n x_{m} = y_{n} xm=yn,则 z k = x m = y n z_{k} = x_{m} = y_{n} zk=xm=yn,且 Z k − 1 Z_{k - 1} Zk1 X m − 1 X_{m - 1} Xm1 Y n − 1 Y_{n - 1} Yn1的最长公共子序列
    • x m ≠ y n x_{m} \neq y_{n} xm=yn z k ≠ x m z_{k} \neq x_{m} zk=xm,则 Z Z Z X m − 1 X_{m - 1} Xm1 Y Y Y的最长公共子序列
    • x m ≠ y n x_{m} \neq y_{n} xm=yn z k ≠ y n z_{k} \neq y_{n} zk=yn,则 Z Z Z X X X Y n − 1 Y_{n - 1} Yn1的最长公共子序列

子问题的递归结构

  • x m = y n x_{m} = y_{n} xm=yn时,找出 X m − 1 X_{m - 1} Xm1 Y n − 1 Y_{n - 1} Yn1的最长公共子序列,然后在其尾部加上 x m x_{m} xm
  • x m ≠ y n x_{m} \neq y_{n} xm=yn时,找出 X m − 1 X_{m - 1} Xm1 Y Y Y的一个最长公共子序列及 X X X Y n − 1 Y_{n - 1} Yn1的一个最长公共子序列,这两个公共子序列中较长者即为 X X X Y Y Y的最长公共子序列
c [ i ] [ j ] c[i][j] c[i][j]递归方程

c [ i ] [ j ] = { 0 , i = 0 或 j = 0 c [ i − 1 ] [ j − 1 ] + 1 , i , j > 0 ; x i = y j max ⁡ { c [ i ] [ j − 1 ] , c [ i − 1 ] [ j ] } , i , j > 0 ; x i ≠ y j c[i][j] = \begin{cases} 0 , & i = 0 或 j = 0 \\ c[i - 1][j - 1] + 1 , & i , j > 0 ; x_{i} = y_{j} \\ \max\set{c[i][j - 1] , c[i - 1][j]} , & i , j > 0 ; x_{i} \neq y_{j} \end{cases} c[i][j]= 0,c[i1][j1]+1,max{c[i][j1],c[i1][j]},i=0j=0i,j>0;xi=yji,j>0;xi=yj


时间复杂性

  • 由于每个数组单元的计算耗费 O ( 1 ) O(1) O(1)时间,因此算法耗时 O ( m n ) O(mn) O(mn)

构造最长公共子序列

  • 在算法 L C S LCS LCS中,每次递归调用使 i i i j j j 1 1 1,因此算法的计算时间为 O ( m + n ) O(m + n) O(m+n)

Python_48">Python实现

def longest_common_subsequence(str_1, str_2):m = len(str_1)n = len(str_2)# 创建一个二维数组来存储子问题的解dp = [[0] * (n + 1) for _ in range(m + 1)]# 填充二维数组for i in range(1, m + 1):for j in range(1, n + 1):if str_1[i - 1] == str_2[j - 1]:dp[i][j] = dp[i - 1][j - 1] + 1else:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])# 构造最长公共子序列lcs = ''i, j = m, nwhile i > 0 and j > 0:if str_1[i - 1] == str_2[j - 1]:lcs = str_1[i - 1] + lcsi -= 1j -= 1elif dp[i - 1][j] > dp[i][j - 1]:i -= 1else:j -= 1return lcsstr_1 = 'ABCDGH'
str_2 = 'AEDFHR'lcs = longest_common_subsequence(str_1, str_2)print(f'最长公共子序列: {lcs}')
最长公共子序列: ADH

算法的改进

  • 如果只需要计算最长公共子序列的长度,则只用到数组 c c c的第 i i i行和第 i − 1 i - 1 i1
  • 因此,用两行的数组空间就可以计算出最长公共子序列的长度,可将空间需求减至 O ( min ⁡ { m , n } ) O(\min\set{m , n}) O(min{m,n})


http://www.ppmy.cn/ops/36247.html

相关文章

[力扣题解] 216. 组合总和 III

题目&#xff1a;216. 组合总和 III 思路 回溯法 代码 class Solution { private:vector<vector<int>> result;vector<int> path;public:void function(int k, int n, int startindex, int sum){int i;// 剪枝// 超过了, 不用找了;if(sum > n){return…

538.把二叉搜索树转换成累加树

给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值 原树中大于或等于 node.val 的值之和。 方法一&#xff1a;递归 class Solution{int sum 0;publ…

泰克示波器如何测量时延?

泰克示波器&#xff08;Tektronix Oscilloscope&#xff09;是一种用于测量和显示电信号的仪器。它可以通过观察电信号的波形来提供有关信号的各种信息&#xff0c;包括幅度、频率和时延。时延是指信号到达示波器的时间延迟&#xff0c;也可以用于测量信号在电路中传播的时间。…

Vector Laboratories|用于生物偶联疗法BioDesign™ dPEG® Linker连接平台

术语dPEG代表“离散PEG&#xff08;discrete PEG&#xff09;”&#xff0c;这是一种均一的、单分子量&#xff08;MW&#xff09;、高纯度的新一代聚乙二醇聚合物。Vector Laboratorie采用其受专利保护的专有生产工艺&#xff0c;可生产提供适合于各种应用场景&#xff0c;具有…

【代码随想录——哈希表】

1.哈希表理论基础 首先什么是 哈希表&#xff0c;哈希表&#xff08;英文名字为Hash table&#xff0c;国内也有一些算法书籍翻译为散列表&#xff0c;大家看到这两个名称知道都是指hash table就可以了&#xff09;。 那么哈希表能解决什么问题呢&#xff0c;一般哈希表都是用…

Candance画运算放大器

根据拉扎维《模拟CMOS集成电路设计》第九章第一个放大器进行搭建电路图。 此电路图中两个NMOS栅极互联是因为NMOS的衬底要接片上最低电压。所以要两个互联并接到最低点。 因为两条支路上的器件都是一样的&#xff0c;所以这两条路平分idc的直流电流。 测试的时候要加上下图这两…

SSL证书选择免费还是付费 ?

目前在市场上既有免费的ssl证书&#xff0c;也有付费的ssl证书&#xff0c;那到底如何选择呢&#xff1f;下面我们来看看二者的区别 1验证级别不同 免费ssl证书通常只提供的是域名验证&#xff08;DV&#xff09;证书&#xff0c;仅验证域名的所有权&#xff0c;不涉及组织身…

重学java 27.异常

要从一座山攀上另一座更高的山&#xff0c;第一步便是下山 —— 24.5.3 知识回顾&#xff1a; 1.权限修饰符 public -> protected -> 默认 -> private a、构造方法一般用public&#xff1a;便于new对象 b、成员方法一般用public&#xff1a;便于调用 c、成员变量的属性…