每日OJ题_回文串dp⑤_力扣516. 最长回文子序列

目录

力扣516. 最长回文子序列

解析代码


力扣516. 最长回文子序列

516. 最长回文子序列

难度 中等

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

示例 1:

输入:s = "bbbab"
输出:4
解释:一个可能的最长回文子序列为 "bbbb" 。

示例 2:

输入:s = "cbbd"
输出:2
解释:一个可能的最长回文子序列为 "bb" 。

提示:

  • 1 <= s.length <= 1000
  • s 仅由小写英文字母组成
class Solution {
public:int longestPalindromeSubseq(string s) {}
};

解析代码

状态表示:

        关于单个字符串问题中的回文子序列,或者回文子串,我们的状态表示研究的对象一般都是选取原字符串中的用段区域 [i, j] 内部的情况。这里继续选取字符串中的一段区域来研究:

dp[i][j] 表示:s 字符串 [i, j] 区间内的所有的子序列中,最长的回文子序列的长度

        状态转移方程: 关于回文子序列和回文子串的分析方式,一般都是比较固定的,都是选择这段区域的左右端点的字符情况来分析。因为如果一个序列是回文串的话,去掉首尾两个元素之后依旧是回文串,首尾加上两个相同的元素之后也依旧是回文串。因为,根据首尾元素的不同,可以分为下面两种情况:

  • 当首尾两个元素相同的时候,也就是 s[i] == s[j] :那么 [i, j] 区间上的最长回文子序列,应该是 [i + 1, j - 1] 区间内的那个最长回文子序列首尾填上 s[i] 和 s[j] ,此时dp[i][j] = dp[i + 1][j - 1] + 2
  • 当首尾两个元素不相同的时候,也就是 s[i] != s[j] :此时这两个元素就不能同时添加在一个回⽂串的左右,那么我们就应该让 s[i] 单独加在⼀个序列的左边,或者让 s[j] 单独放在⼀个序列的右边,看看这两种情况下的最大值:

单独加入 s[i] 后的区间在 [i, j - 1] ,此时最长的回文序列的长度就是 dp[i][j - 1] ;

单独加入 s[j] 后的区间在 [i + 1, j] ,此时最长的回文序列的长度就是 dp[i+ 1][j] ;

取两者的最大值,于是 dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]) ;

综上所述,状态转移方程为:

  • 当 s[i] == s[j] 时: dp[i][j] = dp[i + 1][j - 1] + 2 ;
  • 当 s[i] != s[j] 时: dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]) ;

初始化、填表顺序、返回值:

        根据状态转移方程 dp[i][j] = dp[i + 1][j - 1] + 2 ,状态表示的时候,选取的是⼀段区间,因此需要要求左端点的值要小于等于右端点的值,因此会有两种边界情况:

  • 当 i == j 的时候, i + 1 就会大于 j - 1 ,此时区间内只有一个字符。这个比较好分析, dp[i][j] 表示一个字符的最长回文序列,一个字符能够自己组成回文串,因此此时 dp[i][j] = 1 ;
  • 当 i + 1 == j 的时候, i + 1 也会大于 j - 1 ,此时区间内有两个字符。这样也好分析,当这两个字符相同的时候, dp[i][j] = 2 ; 不相同的时候, d[i][j] = 0 ;

        对于第一种边界情况,在填表的时候就可以同步处理。 对于第二种边界情况, dp[i + 1][j -1] 的值为 0 ,不会影响最终的结果,因此可以不用考虑。

dp[i + 1] 表示下一行的位置, dp[j - 1] 表示前一列的位置,所以从下往上填表,返回dp[0][n - 1];

class Solution {
public:int longestPalindromeSubseq(string s) {int n = s.size();vector<vector<int>> dp(n, vector<int>(n));// dp[i][j] 表示:s 字符串 [i, j]区间内的所有的子序列中,最长的回文子序列的长度for(int i = n - 1; i >= 0; --i) // 枚举左端点i{dp[i][i] = 1; // i等于j的情况for(int j = i + 1; j < n; ++j) // 枚举右端点j{if(s[i] == s[j]) // dp[i + 1][j - 1] 无效就是0dp[i][j] = dp[i + 1][j - 1] + 2;elsedp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);}}return dp[0][n - 1];}
};

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

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

相关文章

stm32cubeMX_io输入输出讲解

1创建项目&#xff08;可在专栏里找到&#xff09; 2进入当前页面点击引脚将弹出下图选项选择输入输出 带点击GPIO 点击引脚弹出如下选项根据需求选择 如有需要可以使用外部时钟&#xff1b;设置如图使用外部时钟 生成代码 将会弹出一个提示点击中间项//打开项目

HarmonyOS NEXT应用开发之MVVM模式

应用通过状态去渲染更新UI是程序设计中相对复杂&#xff0c;但又十分重要的&#xff0c;往往决定了应用程序的性能。程序的状态数据通常包含了数组、对象&#xff0c;或者是嵌套对象组合而成。在这些情况下&#xff0c;ArkUI采取MVVM Model View ViewModel模式&#xff0c;其…

clickhouse 源码编译部署

clickhouse 源码编译部署 版本 21.7.9.7 点击build project&#xff0c;编译工程&#xff0c;经过一定时间&#xff08;第一次编译可能几个小时&#xff0c;后续再编译&#xff0c;只编译有改动的文件&#xff09;生成release目录 在cmake-build-release → programs目录下…

vivado eFUSE 寄存器访问和编程

eFUSE 寄存器访问和编程 注释 &#xff1a; 在 MPSoC 和 Versal 器件上不支持以下 eFUSE 访问和编程方法。 7 系列、 UltraScale 和 UltraScale 器件具有一次性可编程位用于执行特定功能 &#xff0c; 称为 eFUSE 位。不同 eFUSE 位类型如 下所述&#xff1a; • …

单例(Singleton)设计模式

2.1 设计模式概述 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式免去我们自己再思考和摸索。就像是经典的棋谱&#xff0c;不同的棋局&#xff0c;我们用不同的棋谱。"套路" 经典的设计模式共有23种。每个…

语音识别:基于HMM

HMM语音识别的解码过程 从麦克风采集的输入音频波形被转换为固定尺寸的一组声学向量&#xff1a; 其中是维的语音特征向量&#xff08;例如MFCC&#xff09;。 解码器尝试去找到上述特征向量序列对应的单词&#xff08;word&#xff09;的序列&#xff1a; 单词序列的长度是。…

【大数据存储】实验4 NoSQL数据库

实验4 NoSQL数据库 NoSQL数据库的安装和使用实验环境&#xff1a; Ubuntu 22.04.3 Jdk 1.8.0_341 Hadoop 3.2.3 Hbase 2.4.17 Redis 6.0.6 mongdb 6.0.12 mogosh 2.1.0 Redis 安装redis完成 新建终端启动redisredis-server新建一个终端redis-cli 建表操作 尝…

蓝桥杯备考随手记: practise02

问题描述: 有些数字的立方的末尾正好是该数字本身。 比如&#xff1a;1,4,5,6,9,24,25,… 请你计算一下&#xff0c;在10000以内的数字中&#xff08;指该数字&#xff0c;并非它立方后的数值&#xff09;&#xff0c;符合这个特征的正整数一共有多少个。 思路分析: 使用循…

超越传统时序!多模态+时间序列8个创新方案,刷新SOTA

传统时间序列无法有效捕捉数据中复杂的非线性关系&#xff0c;导致在处理具有复杂动力学特性的系统时效果不佳。为解决此问题&#xff0c;研究者提出了多模态时间序列。 在预测任务中&#xff0c;多模态时间序列能够整合来自不同类型数据源的信息&#xff0c;从而提供更全面的洞…

笔记: JavaSE day15 笔记

第十五天课堂笔记 数组 可变长参数★★★ 方法 : 返回值类型 方法名(参数类型 参数名 , 参数类型 … 可变长参数名){}方法体 : 变长参数 相当于一个数组一个数组最多只能有一个可变长参数, 并放到列表的最后parameter : 方法参数 数组相关算法★★ 冒泡排序 由小到大: 从前…

JavaScript(六)---【回调、异步、promise、Async】

零.前言 JavaScript(一)---【js的两种导入方式、全局作用域、函数作用域、块作用域】-CSDN博客 JavaScript(二)---【js数组、js对象、this指针】-CSDN博客 JavaScript(三)---【this指针&#xff0c;函数定义、Call、Apply、函数绑定、闭包】-CSDN博客 JavaScript(四)---【执…

并发编程之线程池的应用以及一些小细节的详细解析

线程池在实际中的使用 实际开发中&#xff0c;最常用主要还是利用ThreadPoolExecutor自定义线程池&#xff0c;可以给出一些关键的参数来自定义。 在下面的代码中可以看到&#xff0c;该线程池的最大并行线程数是5&#xff0c;线程等候区&#xff08;阻塞队列)是3&#xff0c;即…

数据挖掘|关联分析与Apriori算法详解

数据挖掘|关联分析与Apriori算法 1. 关联分析2. 关联规则相关概念2.1 项目2.2 事务2.3 项目集2.4 频繁项目集2.5 支持度2.6 置信度2.7 提升度2.8 强关联规则2.9 关联规则的分类 3. Apriori算法3.1 Apriori算法的Python实现3.2 基于mlxtend库的Apriori算法的Python实现 1. 关联分…

window中如何在Anaconda虚拟环境中安装compressai

1, 进入CompressAI的Github代码页下载压缩包并解压到自己的项目路径 2&#xff0c;打开anaconda的prompt命令行&#xff0c;激活需要安装的虚拟环境&#xff0c;然后进入compressai文件夹&#xff0c;比如下操作&#xff1a; 3&#xff0c;输出安装命令行 pip install -e . -…

redis -String类型用法

一&#xff0c;nosql:泛指非关系型数据库 二 &#xff0c;关系型 和非关系 有什么特点 1&#xff0c;关系型 传统的RDBMS结构化组织SQL数据和关系都存在单独的表中 row col 数据操作&#xff0c;数据定义语言严格的一致性基础的事务。。。。。2&#xff0c;非关系型…

实现读写分离与优化查询性能:通过物化视图在MySQL、PostgreSQL和SQL Server中的应用

实现读写分离与优化查询性能&#xff1a;通过物化视图在MySQL、PostgreSQL和SQL Server中的应用 在数据库管理中&#xff0c;读写分离是一种常见的性能优化方法&#xff0c;它通过将读操作和写操作分发到不同的服务器或数据库实例上&#xff0c;来减轻单个数据库的负载&#x…

企业必备! 防员工偷懒神器,工作状况一目了然

在当前企业管理中&#xff0c;员工的工作状态和工作效率一直是管理者们关注的焦点。为了更加有效地监管员工的工作微信使用情况&#xff0c;微信管理系统成为了企业必备的神器。 这款系统不仅可以实时监控员工的工作微信&#xff0c;还具有多种实用功能&#xff0c;帮助企业管…

Redis分布式锁常见面试题

文章目录 1.Redis分布式锁是如何实现的2.Redisson实现分布式锁如何合理的控制锁的有效时长3.Redisson的这个锁&#xff0c;可以重入吗4.Redisson锁能解决主从数据一致的问题吗 1.Redis分布式锁是如何实现的 ● 先按照自己简历上的业务进行描述分布式锁使用的场景 ● 我们当时使…

查看图片某点亮度

一背景 光强度的评价通常涉及对光源发出的光的量进行测量和描述。这种评价可以通过多种方式进行&#xff0c;但最常见的是使用光强单位“坎德拉”&#xff08;candela&#xff0c;cd&#xff09;来表示。坎德拉是国际单位制&#xff08;SI&#xff09;中光强度的单位&#xff…

2024 蓝桥打卡Day31

递归与辗转相除法 递归&#xff08;Recursion&#xff09;辗转相除法&#xff08;Euclidean Algorithm&#xff09;总结 递归&#xff08;Recursion&#xff09; 递归是指一个函数在执行过程中调用自身的过程。在编程中&#xff0c;递归函数在遇到满足某个条件时会停止调用自身…