区间动态规划——最长回文子串(C++)

news2024/7/2 21:11:18

难得心静。

——2024年6月30日


  什么是区间动态规划?

        区间动态规划通常以连续区间的求解作为子问题,例如区间 [i, j] 上的最优解用dp[i][j]表示。先在小区间上进行动态规划得到子问题的最优解,再利用小区间的最优解合并产生大区间的最优解
        所以区间动态规划一般需要从小到大枚举所有可能的区间,在枚举时不能向平常的从头到尾遍历,而是以区间长度len为循环变量,在不同的区间长度中枚举所有的可能状态,并从中选取最优解。

区间动态规划区别于一般的动态规划:以区间长度len作为循环变量。 


下面以LeetCode5最长回文子串为例:

LeetCode5——最长回文子串

题目描述

        给定一个字符串s(s仅由数字和英文大小写字母组成,长度为1~1000),求s中最长的回文子串。例如,s = “babad”,最长的回文子串有“bab”和“aba”,求出任意一个均可。

题解思路

        区间动态规划

1. 定义dp数组

        定义 dp[i][j ]表示 s[i...j] 是否为回文子串,dp的数值用true和false表示。例如 s = “aba”,那么dp[0][2] = true,dp[0][1] = false;

动态规划的问题,dp的含义都是自己给的,给出含义之后就需要去列关系求解了。

2. 确定dp限制条件

注:len表示字符串长度

        ①对于任何 len == 1 的字符串,dp[i][j] = 1

        ②对于任何 len == 2 的字符串,dp[i][j] = (s[i] == s[j]);(如果s[i] == s[j], 说明该长度为2的字符串是回文串,比如说“aa”)

        ③对于任何 len  ≥  3 的字符串, dp[i][j] = (dp[i+1][j-1] && s[i] == s[j])

解释如下:

        第一种情况很好理解,如果字符串长度为1的话,那么他一定是回文子串;

        第二种情况也很好理解,如果字符串长度为2,那么只需要判断这两个字符是否相等即可,如果相等则为回文子串,反之则不是;

        第三种情况,字符串长度不小于3时,你就需要想到你定义的dp含义和回文字符串的性质了,dp[i][j ]表示 s[i...j] 是否为回文子串要判断s[i...j]是否为回文子串,那么就必须先知道s[i+1...j-1]是否为回文子串,然后再判断s[i]是否等于s[j],两者都满足的话那dp[i][j]就等于true了,只要有一个不满足,那么dp[i][j]就为false。

Tips

        前两种情况是小区间的最优解,第三种情况就是大区间的最优解。

        其实动态规划的问题本质上就是求取了子问题的最优解之后,不断根据子问题的值更新当前dp数组的值,比如非常经典的背包问题。

3. 更新目标字符串长度

        不断更新目标字符串长度,只要出现 dp[i][j]=true 的情况就进行更新,并利用substr函数打印即可。(这里如果不理解请看代码部分) 


 代码实现

再次提醒:区间动态规划的特点是以len为循环变量

区间动态规划伪代码:

for(int len = 1; len <= 序列长度; len++){
    for(int i = 0; i + len - 1 < 序列长度; i++){
        int j = i + len - 1;
        i和j就是区间的端点,i与j相距len个长度。
    }
}

关键代码:

// 获取最长回文子串
string getLongestStr(string s){
    int n = s.size();
    string ans = "";
    // 定义dp数组
    // dp[i][j]表示从i到j的子字符串是否为回文串
    vector<vector<bool>> dp(n, vector<bool> (n, false));

    // len从1开始
    for(int len = 1; len <= n; len++){
        for(int i = 0; i + len - 1 < n; i++){
            int j = i + len - 1;
            if(len == 1){
                dp[i][j] = true;
            }
            else if(len == 2){
                dp[i][j] = (s[i] == s[j]);
            }
            else{
                dp[i][j] = (s[i] == s[j] && dp[i+1][j-1]);
            }
            if(dp[i][j] && ans.size() < len){
                ans = s.substr(i, len);//更新回文子串
            }
        }
    }
    return ans;
}

结果展示

 

完整代码

// 区间动态规划
#include<iostream>
#include<vector>
#include<string>

using namespace std;

// 获取最长回文子串
string getLongestStr(string s){
    int n = s.size();
    string ans = "";
    // 定义dp数组
    // dp[i][j]表示从i到j的子字符串是否为回文串
    vector<vector<bool>> dp(n, vector<bool> (n, false));

    // len从1开始
    for(int len = 1; len <= n; len++){
        for(int i = 0; i + len - 1 < n; i++){
            int j = i + len - 1;
            if(len == 1){
                dp[i][j] = true;
            }
            else if(len == 2){
                dp[i][j] = (s[i] == s[j]);
            }
            else{
                dp[i][j] = (s[i] == s[j] && dp[i+1][j-1]);
            }
            if(dp[i][j] && ans.size() < len){
                ans = s.substr(i, len);
            }
        }
    }
    return ans;
}



int main(){
    string s;
    cout<<"请输入字符串s:";
    cin>>s;
    cout<<"最长回文子串为"<<getLongestStr(s)<<endl;
    return 0;
}

         看完了是否意犹未尽呢,那再把这个题变一下 ,我现在想求最长回文子序列(或者它的长度)应该怎么做?题目解释:比如我有一个字符串为:s = “aferegga”,那它的最长回文子序列为“aerea”,它的长度为5。

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

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

相关文章

ComfyUI高清放大的四种方式(工作流附件在最后)

方式一&#xff1a;Latent放大工作流 1.工作流截图 方式二&#xff1a;ESRGAN&#xff08;传统模型&#xff09;放大工作流 方式三&#xff1a;算法放大&#xff08;后期处理&#xff09;工作流 方式四&#xff1a;Ultimate SD Upscale工作流 这个方式的优势是对于显存底的用…

WP黑格导航主题BlackCandy

BlackCandy-V2.0全新升级&#xff01;首推专题区(推荐分类)更多自定义颜色&#xff01;选择自己喜欢的色系&#xff0c;焕然一新的UI设计&#xff0c;更加扁平和现代化&#xff01; WP黑格导航主题BlackCandy

代码随想录第37天|动态规划

01背包理论基础 参考 01背包: 每个物品只有一个, 只要选或不选两个选项 暴力解法: 回溯法枚举 dp[i][j]: i 表示 0 ~ i 的物品, j 表示容量, 数值表示当前的最大价值递推公式: max(dp[i-1][j], dp[i-1][j-weight[i]] value[i])初始化: j 0 时, 无法放任何有价值的物品, d…

目标检测常用涨点方法:注意力机制小结(空间注意力、通道注意力、CBAM等)

1.通道注意力 通道注意力&#xff08;Channel Attention&#xff09;是在通道维度上对输入数据进行学习&#xff0c;再对不同的通道分配相应的权重表示重要性&#xff0c;从而达到“分配注意力”的效果。SENet&#xff08;Squeeze and Excitation networks) 是一个典型的使用通…

MySQL高级-事务-并发事务演示及隔离级别

文章目录 0、四种隔离级别1、创建表 account2、修改当前会话隔离级别为 read uncommitted2.1、会出现脏读 3、修改当前会话隔离级别为 read committed3.1、可以解决脏读3.2、会出现不可重复读 4、修改当前会话隔离级别为 repeatable read&#xff08;默认&#xff09;4.1、解决…

C++(Python)肥皂泡沫普拉托边界膜曲面模型算法

&#x1f3af;要点 &#x1f3af;肥皂泡二维流体模拟 | &#x1f3af;泡沫普拉托边界膜曲面模型算法演化厚度变化 | &#x1f3af;螺旋曲面三周期最小结构生成 &#x1f4dc;皂膜用例&#xff1a;Python计算物理粒子及拉格朗日和哈密顿动力学 | Python和MATLAB粘性力接触力动…

ELK企业级实战

一、Elstic stack在企业的常⻅架构 https://www.bilibili.com/video/BV1x94y1674x/?buvidXY705117E90F73A790429C9CFBD5F70F22168&vd_source939ea718db29535a3847d861e5fe37ef ELK 解决取得问题 痛点1: ⽣产出现故障后&#xff0c;运维需要不停的查看各种不同的⽇志进⾏…

10款好用不火的PC软件,真的超好用!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/市场上有很多软件&#xff0c;除了那些常见的大众化软件&#xff0c;还有很多不为人知的小众软件&#xff0c;它们的作用非常强大&#xff0c;简洁…

骁龙相机拍照流程分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 1.deliverInputEvent 拍照点击事件处理 2.submitRequestList Camera 提交拍照请求 3.createCaptureRequest 拍照请求帧数 骁龙相机通过binder 数据传输…

小程序打包

一、manifest.json文件添加小程序id 二、接口校验&#xff0c;后端接口添加正式上线&#xff0c;有域名的地址 然后到微信公众平台-开发管理-服务器域名处配置request合法域名&#xff0c;在 此处能够看到后端的baseUrl 三、项目部署 四、发版 在小程序编辑器里 此处可以在…

微服务之服务保护策略【持续更新】

文章目录 线程隔离一、滑动窗口算法二、漏桶算法三、令牌桶算法 面试题1、Sentinel 限流和Gateway限流的区别 线程隔离 两种实现方式 线程池隔离&#xff08;Hystix隔离&#xff09;&#xff0c;每个被隔离的业务都要创建一个独立的线程池&#xff0c;线程过多会带来额外的CPU…

Android跨进程通信,binder传输数据过大导致客户端APP,Crash,异常捕获,监听异常的数值临界值,提前Hook拦截。

文章目录 Android跨进程通信&#xff0c;binder传输数据过大导致Crash&#xff0c;异常捕获&#xff0c;监听异常的数值临界值&#xff0c;提前Hook拦截。1.binder在做跨进程传输时&#xff0c;最大可以携带多少数据1.1有时候这个1m的崩溃系统捕获不到异常&#xff0c; 2.监测异…

大模型系列课程学习-基于2080TI-22G魔改卡搭建双卡大模型训练平台(双系统)

1.选择合适的硬件配置 再配置电脑之前&#xff0c;需要确认自己需要的显存大小、主板、内存条、电源、散热等核心配件。经过前期调研&#xff0c;选择的硬件配置如下&#xff1a; &#xff08;1&#xff09;主板&#xff1a;华南X99_F8D(DDR4主板)&#xff0c;因为需要支持双卡…

springboot 3.x相比之前版本有什么区别

Spring Boot 3.x相比之前的版本&#xff08;尤其是Spring Boot 2.x&#xff09;&#xff0c;主要存在以下几个显著的区别和新特性&#xff1a; Java版本要求&#xff1a; Spring Boot 3.x要求至少使用Java 17作为最低版本&#xff0c;同时已经通过了Java 19的测试&#xff0c;…

【C语言】指针剖析(完结)

©作者:末央&#xff06; ©系列:C语言初阶(适合小白入门) ©说明:以凡人之笔墨&#xff0c;书写未来之大梦 目录 回调函数概念回调函数的使用 - qsort函数 sizeof/strlen深度理解概念手脑并用1.sizeof-数组/指针专题2.strlen-数组/指针专题 指针面试题专题 回调函…

C++ | Leetcode C++题解之第205题同构字符串

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isIsomorphic(string s, string t) {unordered_map<char, char> s2t;unordered_map<char, char> t2s;int len s.length();for (int i 0; i < len; i) {char x s[i], y t[i];if ((s2t.coun…

HDFS详细介绍以及HDFS集群环境部署【hadoop组件HDFS笔记】(图片均为学习时截取的)

HDFS详细介绍 HDFS是什么 HDFS是Hadoop三大组件(HDFS、MapReduce、YARN)之一 全称是&#xff1a;Hadoop Distributed File System&#xff08;Hadoop分布式文件系统&#xff09;&#xff1b;是Hadoop技术栈内提供的分布式数据存储解决方案 可以在多台服务器上构建存储集群&…

C : 线性规划例题求解

Submit Page TestData Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 93 Solved: 49 Description 求解下述线性规划模型的最优值min &#xfffd;1&#xfffd;1&#xfffd;2&#xfffd;2&#xfffd;3&#xfffd;3&#xfffd;.&#xfffd;. &…

Java 并发编程常见问题

1、线程状态它们之间是如何扭转的&#xff1f; 1、谈谈对于多线程的理解&#xff1f; 1、对于多核CPU&#xff0c;多线程可以提升CPU的利用率&#xff1b; 2、对于多IO操作的程序&#xff0c;多线程可以提升系统的整体性能及吞吐量&#xff1b; 3、使用多线程在一些场景下可…

StringUTF_16错误认识字节长度

众所周知&#xff0c;在 UTF-8 编码中&#xff0c;中文字符通常占用 3 个字节: import java.nio.charset.StandardCharsets;/*** author shenyang* version 1.0* info untitled* since 2024/6/30 上午9:42*/ public class Test {public static void main(String[] args) {Stri…