首页 > 编程语言 >(算法)最⻓公共⼦序列————<动态规划>

(算法)最⻓公共⼦序列————<动态规划>

时间:2024-10-29 15:45:14浏览次数:5  
标签:状态表 int s2 s1 算法 公共 序列 dp

1. 题⽬链接:1143.最⻓公共⼦序列

2. 题⽬描述:

3. 解法(动态规划):

算法思路:

1. 状态表⽰:

对于两个数组的动态规划,我们的定义状态表⽰的经验就是:

        i. 选取第⼀个数组[0, i] 区间以及第⼆个数组[0, j] 区间作为研究对象;

        ii. 结合题⽬要求,定义状态表⽰。 在这道题中,我们根据定义状态表⽰为: dp[i][j] 表⽰: s1 的[0, i] 区间以及s2 的[0, j] 区间内的所有的⼦序列中,最 ⻓公共⼦序列的⻓度。

2. 状态转移⽅程:

分析状态转移⽅程的经验就是根据「最后⼀个位置」的状况,分情况讨论。 对于dp[i][j] ,我们可以根据s1[i] 与s2[j] 的字符分情况讨论:

        i. 两个字符相同, s1[i] = s2[j] :那么最⻓公共⼦序列就在s1 的[0, i - 1] 以 及s2 的[0, j - 1] 区间上找到⼀个最⻓的,然后再加上s1[i] 即可。因此dp[i][j] = dp[i - 1][j - 1] + 1 ;

        ii. 两个字符不相同, s1[i] != s2[j] :那么最⻓公共⼦序列⼀定不会同时以s1[i] 和s2[j] 结尾。那么我们找最⻓公共⼦序列时,有下⾯三种策略:

                • 去s1 的[0, i - 1] 以及s2 的[0, j] 区间内找:此时最⼤⻓度为dp[i - 1][j] ;

                • 去s1 的[0, i] 以及s2 的[0, j - 1] 区间内找:此时最⼤⻓度为dp[i ] [j - 1] ;

                • 去s1 的[0, i - 1] 以及s2 的[0, j - 1] 区间内找:此时最⼤⻓度为 dp[i - 1][j - 1] 。 我们要三者的最⼤值即可。但是我们细细观察会发现,第三种包含在第⼀种和第⼆种情况⾥ ⾯,但是我们求的是最⼤值,并不影响最终结果。因此只需求前两种情况下的最⼤值即可。

综上,状态转移⽅程为: if(s1[i] == s2[j]) dp[i][j] = dp[i - 1][j - 1] + 1 ; if(s1[i] != s2[j]) dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) 。

3. 初始化:

a. 「空串」是有研究意义的,因此我们将原始dp 表的规模多加上⼀⾏和⼀列,表⽰空串。

b. 引⼊空串后,⼤⼤的⽅便我们的初始化。

c. 但也要注意「下标的映射关系」,以及⾥⾯的值要「保证后续填表是正确的」。 当s1 为空时,没有⻓度,同理s2 也是。因此第⼀⾏和第⼀列⾥⾯的值初始化为0 即可保证 后续填表是正确的。

4. 填表顺序:

根据「状态转移⽅程」得:从上往下填写每⼀⾏,每⼀⾏从左往右。

5. 返回值:

根据「状态表⽰」得:返回dp[m][n] 。 

C++算法代码: 

class Solution 
{
public:
    int longestCommonSubsequence(string text1, string text2) 
    {
        int n1=text1.size(),n2=text2.size();
        //优化
        text1=' '+text1;
        text2=' '+text2;
        //建表
        vector<vector<int>>dp(n1+1,vector<int>(n2+1));
        //填表
        for(int i=1;i<=n1;i++)
        {
            for(int j=1;j<=n2;j++)
            {
                if(text1[i]==text2[j])
                {
                    dp[i][j]=dp[i-1][j-1]+1;
                }
                else
                {
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        //返回值
        return dp[n1][n2];
    }
};

Java算法代码:

class Solution
{
	public int longestCommonSubsequence(String s1, String s2)
	{
		// 1. 创建 dp 表 
		// 2. 初始化 
		// 3. 填表 
		// 4. 返回值 
		int m = s1.length(), n = s2.length();
		s1 = " " + s1; s2 = " " + s2;
		int[][] dp = new int[m + 1][n + 1];
		for (int i = 1; i <= m; i++)
			for (int j = 1; j <= n; j++)
				if (s1.charAt(i) == s2.charAt(j))
					dp[i][j] = dp[i - 1][j - 1] + 1;
				else
					dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
		return dp[m][n];
	}
}

标签:状态表,int,s2,s1,算法,公共,序列,dp
From: https://blog.csdn.net/2301_79580018/article/details/143331189

相关文章

  • 点云学习笔记4——点云滤波降采样后进行4PCS粗配准【四点一致集配准算法(4-Point Congr
    #include<iostream>#include<pcl/point_cloud.h>#include<pcl/point_types.h>#include<pcl/filters/voxel_grid.h>#include<pcl/common/common_headers.h>#include<pcl/io/pcd_io.h>#include<pcl/visualization/cloud_vi......
  • DRF-Serializers序列化器组件源码分析及改编su
    1.源码分析注意:以下代码片段为方便理解已进行简化,只保留了与序列化功能相关的代码序列化的源码中涉及到了元类的概念,我在这里简单说明一下:元类(metaclass)是一个高级概念,用于定义类的创建行为。简单来说,元类是创建类的类,它决定了类的创建方式和行为。在Python中一切皆为对象,包......
  • 【回溯算法】(第七篇)
    目录⼦集(medium)题目解析讲解算法原理编写代码找出所有⼦集的异或总和再求和(easy)题目解析讲解算法原理编写代码⼦集(medium)题目解析1.题目链接:.-力扣(LeetCode)2.题目描述给你⼀个整数数组nums,数组中的元素互不相同。返回该数组所有可能的⼦集(幂集)。解集不能包......
  • 【综合算法练习】(第八篇)
    目录全排列Ⅱ(medium)题目解析讲解算法原理编写代码电话号码的字⺟组合(medium)题目解析讲解算法原理编写代码全排列Ⅱ(medium)题目解析1.题目链接:.-力扣(LeetCode)2.题目描述给定⼀个可包含重复数字的序列nums,按任意顺序返回所有不重复的全排列。•⽰例1:输⼊:num......
  • 百度二面算法:合法的括号字符串
    目录标题1.题目1.1示例2.利用栈求解2.1代码结构分析2.1.1代码优缺点1.题目给定一个字符串s,字符串s只包含以下三种字符:(,*,),请你判断s是不是一个合法的括号字符串。合法括号字符串有如下规则:左括号’(‘必须有对应的右括号’)’右括号’)‘必须有对应的左括号......
  • 算法与数据结构——计数排序
    计数排序计数排序(countingsort)通过统计元素数量来实现排序,通常应用于整数数组。简单实现给定一个长度为n的数组nums,其中的元素都是“非负整数”,计数排序的整体流程如下:遍历数组,找出其中最大的数组,记为m,然后创建一个长度为m+1的辅助数组counter。借助counter统计nums中各......
  • 抖音中aBogus签名算法的纯Python代码实现(2024年10月)
    目前网上的aBogus签名算法都是用python里execjs来执行js代码计算的,这种方法虽然可以达到计算签名值的结果,但是性能不高。本文直接将aBogus的js的源码改成python代码,同样的参数,计算的结果和js版本一样。附python源码importjsonfromrandomimportchoicefromrandomimport......
  • 【C++】—— priority_queue :平衡效率与秩序的算法利器
    去感受一棵草、一缕风、一场日落,去重新触摸真正的生活。——高盛元目录1、优先级队列1.1什么是优先级队列1.2 priority_queue的使用1.3仿函数2、priority_queue的模拟实现2.1整体框架接口2.2插入&&向上调整2.2删除&&向下调整2.3其他接口2.4优先级队列的应用......
  • 对称加密算法和非对称加密算法
    目录对称加密(SymmetricEncryption)非对称加密(AsymmetricEncryption)对比分析应用场景RSA加密算法是一种非对称加密算法。AES算法全称AdvancedEncryptionStandard,又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且......
  • RSA加密算法实现
    Java实现RSA加密算法示例,包括密钥对的生成、加密和解密过程。首先需要导入Java的加密库,这些功能主要通过java.security和javax.crypto包提供。先生成了一个RSA密钥对,包括一个公钥和一个私钥。然后使用公钥加密了一个字符串,并使用私钥解密了加密后的字符串。加密和解密的结果都......