Leetcode 1143. 最长公共子序列 记忆化搜索 优化 C++实现

news2024/11/15 19:52:29

Leetcode 1143. 最长公共子序列

问题:给定两个字符串 text1  text2,返回这两个字符串的最长公共子序列的长度。如果不存在公共子序列,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

算法1:递归搜索 + 保存计算结果 = 记忆化搜索

创建二维数组 memo 并赋初始值  -1-1 代表这个元素没有被计算过。

进入函数 dfs :如果两个字符相同,那么两个指针同时向后移动一个位置,进入下一层递归,计数器 +1

代码:

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int n = text1.length(),m = text2.length();
        vector<vector<int>> memo(n,vector<int>(m,-1));// -1代表没被选过
        auto dfs = [&](auto &&dfs,int i,int j) -> int{
            if(i < 0 || j < 0)  return 0;
            int &res = memo[i][j]; // 注意这里是引用
            if (res != -1) return res; // 之前计算过
            if (text1[i] == text2[j]) return res = dfs(dfs, i - 1, j - 1) + 1;
            return res = max(dfs(dfs, i - 1, j), dfs(dfs, i, j - 1));
        };
        return dfs(dfs, n - 1, m - 1);
    }
};

算法2:1:1 翻译成递推

创建二维数组 dp ,并赋初始值为 0dp [ i + 1 ] [ j +1 ] 表示 text1 的前 i 个字符与 text2 的前 j 个字符中的最长子序列长度。

当 text1 [ i ] == text2 [ j ] 时,dp [ i + 1 ] [ j +1 ] = dp [ i ] [ j ] + 1

 text1 [ i ]  != text2 [ j ] 时,dp [ i + 1 ] [ j +1 ] = max ( dp [ i ] [ j + 1 ] , dp [ i + 1] [ j ] )

代码:

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int n = text1.length(), m = text2.length();
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                dp[i + 1][j + 1] = text1[i] == text2[j] ? dp[i][j] + 1 : max(dp[i][j + 1], dp[i + 1][j]);
        return dp[n][m];
    }
};

算法3:空间优化:两个数组(滚动数组)

通过算法2可以发现,二维数组 dp 的列空间只用到了相邻的两个位置,即 dp [ i + 1 ] [ ] dp [ i ] [ ] ,所以我们可以把列空间优化,即把 dp 数组变为 2行 m+1 列 ,通过取余( % )操作,可以循环利用这两个空间。

最后 return dp [n % 2 ] [ m ] 的原因是要从 dp[ 0 ][ 0 ] 开始递归,所以 假设 n = 5 n % 2 1 ,我们就要 return dp [ 1 ] [ m ]

代码:

class Solution {
public:
    int longestCommonSubsequence(string s, string t) {
        int n = s.length(), m = t.length();
        vector<vector<int>> dp(2, vector<int>(m + 1));
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                dp[(i + 1) % 2][j + 1] = s[i] == t[j] ? dp[i % 2][j] + 1 : max(dp[i % 2][j + 1], dp[(i + 1) % 2][j]);
        return dp[n % 2][m];
    }
};

算法4:空间优化:一个数组

dp [ j + 1 ] 表示 text2 前 j 个元素与当前遍历到的 text1 的元素的最长子序列长度。

pre 表示先前 dp [ j + 1 ] 的状态,当 j 更新后,也就是此时的 dp [ j ] 的上一个值(没在本轮更新过的值)。这个操作保证了在遍历 text2 时,如果出现相同的字母,不会重复计算。例如,当前遍历到了 text1 的第一个 a ,刚好 text2 aca ,遍历 text2 过程中,遍历到第一个 a 时,个数 + 1,遍历到第二个 时,pre 等于这个位置之前的值,因为 a == a ,所以 dp = pre + 1 ,这样不会出现元素重复计算的情况,因为无论 text2 的这个元素是否与 text1 当前正遍历到的元素 相等,他们更新的 dp 值都相同,因为如果这两个元素不相等,如果前面的 dp 已经更新,那么此 dp 也会通过 max 操作更新。

代码中出现 j + 1 的原因是因为 text1 text2 中元素都是从下标 0 开始存储,而 dp 数组从下标 1 开始存储。

代码:

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int m = text2.length();
        vector<int> dp(m+1);
        for(char x : text1)
            for(int j = 0,pre = 0;j < m;j++){
                int temp = dp[j + 1];
                dp[j + 1] = x == text2[j] ? pre + 1 : max(dp[j],dp[j + 1]);
                pre = temp;
            }
        return dp[m];
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2101238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一体化智能电动窗帘:开启智能生活新时尚

史新华 在科技不断进步的今天&#xff0c;人们对生活品质的追求也越来越高。电动窗帘作为智能家居的重要组成部分&#xff0c;以其便捷、智能、时尚的特点&#xff0c;正逐渐走进千家万户。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 一、电动窗帘…

KEYSIGHT U2020 X系列 USB峰值和均值功率传感器

​ _是德(KEYSIGHT) _ U2020 X系列 USB峰值和均值功率传感器 苏州新利通仪器仪表 U2020 X 系列功率传感器得到 Keysight BenchVue 软件的支持。使用 BenchVue 软件&#xff0c;您无需编程便可轻松控制功率计记录数据&#xff0c;并以各种形式显示测量结果。 只需将传感器…

AI大模型与量子纠缠理论的结合,以及相关应用思考

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下AI大模型与量子纠缠理论的结合&#xff0c;以及相关应用思考。将大模型&#xff08;LLM&#xff09;的基本原理与量子纠缠理论相结合是一个高度抽象的概念。我们首先需要理解这两个领域的基本原理&#xff0c;然后探…

#ARM开发 笔记

课程介绍 ARM开发 --> Linux移植 --> 驱动开发 前后联系&#xff1a;ARM和系统移植为驱动开发学习做准备工作 所需知识&#xff1a;C语言基础及STM32需要的硬件知识 学习方法 学习流程、思想和解决问题的方法即可 知道驱动的基本框架以及基本开发要求 底层课程导学 接口技…

NTFS安全权限和文件共享

一.常见文件系统 NTFS 描述&#xff1a; Windows最常使用的文件系统&#xff08;New Technology File System&#xff09;微软公司开发的一种专用于 Windows 操作系统的文件系统。 特点&#xff1a; 效率性 可以提高磁盘的读写性能&#xff1b; 可靠性 加密文件系统访问控制列…

Vue组件:使用Prop实现父组件向子组件传递数据

1、Prop 基本用法 由于组件实例的作用域是孤立的&#xff0c;因此子组件的模板无法直接应用父组件的数据。如果想要通过父组件向子组件传递数据&#xff0c;就需要定义 Prop。Prop 是父组件用来传递数据的一个自定义属性&#xff0c;这样的属性需要定义在组件选项对象的 props…

并发集合(二):CopyOnWriteArrayList

1、CopyOnWriteArrayList介绍 CopyOnWriteArrayList 是一个线程安全的ArrayList。 CopyOnWriteArrayList 是基于Lock锁和线程副本的形式来保证线程安全的&#xff0c; 在写数据时&#xff0c;先获取Lock锁&#xff0c;然后复制一个副本&#xff0c;添加数据时&…

Delphi7实现Json对象的序列化与反序列化

在高版本的 Delphi 中&#xff0c;实现序列化和反序列化非常简单。然而&#xff0c;在 Delphi 7 中&#xff0c;这个过程仍然需要一些额外的努力。为了简化这个问题&#xff0c;我花了一些时间封装了一个支持序列化和反序列化的 JSON 解析库。 type{$M}TStartupParameters cla…

MySQL的服务器与客户端:架构解析与实践

文章目录 MySQL的服务器和客户端服务端处理客户端请求连接管理解析与优化查询缓存语法解析查询优化 存储引擎不同的存储引擎查看支持的存储引擎为不同的表设置存储引擎 MySQL是一个广泛使用的开源关系数据库管理系统&#xff0c;其核心架构由服务器端和客户端两大部分组成。本文…

9/3 链表-力扣160 、203、206

160.相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函…

CUDA-MODE课程笔记 第9课: 归约(也对应PMPP的第10章)

我的课程笔记&#xff0c;欢迎关注&#xff1a;https://github.com/BBuf/how-to-optim-algorithm-in-cuda/tree/master/cuda-mode CUDA-MODE课程笔记 第9课: 归约&#xff08;也对应PMPP的第10章&#xff09; 课程笔记 本节课的题目。 这节课的内容主要是 Chapter 10 of PMPP …

TCP连接重置,到底怎么回事?还是得网工大佬来分析!

来源&#xff1a;科来。 连接建立失败并不仅仅包含无响应问题&#xff0c;还有一种常见的情况&#xff0c;即RST&#xff08;Reset&#xff09;包的发送。RST包是TCP协议中用来进行“连接重置”的数据包&#xff0c;本文将围绕RST包进行详细展开讨论。 TCP连接中为何会有RST包…

VideoCrafter1:Open Diffusion models for high-quality video generation

https://zhuanlan.zhihu.com/p/677918122https://zhuanlan.zhihu.com/p/677918122 视频生成无论是文生视频,还是图生视频,图生视频这块普遍的操作还是将图片作为一个模态crossattention进unet进行去噪,这一步是需要训练的,svd除此之外,还将图片和noise做拼接,这一步,很…

【压测】ab命令

安装 sudo yum install httpd-toolssudo apt update sudo apt install apache2-utils介绍 ab&#xff1a;参数数量错误 用法&#xff1a;ab [选项] [http[s]://]主机名[:端口]/路径 选项包括&#xff1a; -n 请求次数 执行的请求数 -c 并发数 同时发起的多个请求数量 -t 时间…

springboot博客系统

基于springbootvue实现的博客系统 &#xff08;源码L文ppt&#xff09;4-031 4 系统设计 博客系统的整体结构设计主要分为两大部分&#xff1a;管理员和博主。他们的权限不同&#xff0c;于是操作功能也有所不同。整体结构设计如图4-2所示。 图4-2 系统结构图 4.3 数据库设…

HALCON与LabVIEW的联合编程 视觉与控制结合

HALCON与LabVIEW的联合编程在工业自动化和视觉检测领域中越来越受到重视。通过将HALCON的强大图像处理能力与LabVIEW的灵活控制功能相结合&#xff0c;工程师们可以开发出高效且精确的自动化系统。这种整合不仅提高了系统的整体性能&#xff0c;还简化了开发流程。本文将详细介…

前端DatePicker组件设置默认日期并限制可选日期范围

前言 在前端 element-ui 组件库中有一款组件叫做 DatePicker&#xff0c;是一个灵活选择日期的封装组件&#xff0c;它既能选择单个日期&#xff0c;也能选择一个日期范围&#xff08;两个日期的组合&#xff09;&#xff0c;后者的应用场景主要有以下两类&#xff1a;1、作为…

妙用市场情绪找出大盘买卖点,逆向交易5年3倍|邢不行

这是邢不行第 118 期量化小讲堂的分享 作者 | 邢不行、密斯锌硒 前言&#xff1a;有这么一个交易品种&#xff0c;它时而是身披圣光的天使&#xff0c;让人一夜间财富暴涨&#xff0c;时而又化身诱人疯狂的恶魔&#xff0c;让人一息间血本无归&#xff0c;我们似乎很了解它&a…

基于plc的变压器冷却系统设计(论文+源码)

1总体方案设计 通过需求分析&#xff0c;本设计基于PLC的变压器冷却系统的整体结构如图2.1所示&#xff0c;系统采用S7-200 PLC为控制器&#xff0c;其结合温度传感器、电压电流传感器、主风机、备用风机等构成整个系统&#xff0c;具有手动和自动两种模式&#xff0c;在手动模…

C++——入门基础(下)

目录 一、引用 &#xff08;1&#xff09;引用的概念和定义 &#xff08;2&#xff09;引用的特性 &#xff08;3&#xff09;引用的使用 &#xff08;4&#xff09;const引用 &#xff08;5&#xff09;指针和引用的关系 二、inline 三、nullptr 四、写在最后 一、引用…