【动态规划专栏】-- 回文串问题 -- 动态规划经典题型

news2024/11/16 17:30:58

目录

动态规划

动态规划思维(基础)

状态表示(最重要)

状态转移方程(最难)

初始化(细节)

填表顺序(细节)

返回值(结果)

回文子串 ⭐⭐

【题目解析】 

【算法原理】

C++ 算法代码 

最长回文子串 ⭐⭐ 

【题目解析】 

【算法原理】

C++ 算法代码  

回文串分割Ⅳ⭐⭐⭐ 

【题目解析】 

【算法原理】

C++ 算法代码


动态规划

动态规划思维(基础)

        动态规划一般会先定义一个dp表,dp表一般为一维数组 / 二位数组。如:一维数组,会先创建一个一维数组(dp表),接下来就是想办法将这个dp填满,而填满之后里面的某一个值就是最终结果。

状态表示(最重要)

#问:是什么?

  • 就是dp[i]所代表的含义。

#问:怎么来?

  • 题目要求。
  • 经验 + 题目要求。
  • 分析问题的过程中,发现重复子问题。

状态转移方程(最难)

#问:是什么?

  • dp[i] = ?。

初始化(细节)

#问:有什么作用?

  • 保证填表的时候不越界。

        dp表是根据状态转移方程进行的,而状态转移方程是通过已有状态推出未知状态。

填表顺序(细节)

#问:有什么作用?

  • 为了填写当前状态的时候,所需要的状态已经计算过了。

返回值(结果)

        题目要求 + 状态表示。

⭐⭐⭐DP解回文串问题核心:能够将所有的字串是否是回文的信息,保存在dp表中。


回文子串 ⭐⭐

 647. 回文子串 - 力扣(LeetCode)


【题目解析】 

        为了能表示出来所有的子串,我们可以创建⼀个 n * n 的⼆维 dp 表,只用到「上三角部分」即可。 其中, dp[i][j] 表示: s 字符串 [i, j] 的子串,是否是回文串

        每层逻辑。

【算法原理】

#:状态表示:

        为了能表示出来所有的子串,我们可以创建⼀个 n * n 的⼆维 dp 表,只用到「上三角部分」
即可。 其中, dp[i][j] 表示: s 字符串 [i, j] 的子串,是否是回文串。

#:状态转移方程:

对于回文串,我们⼀般分析⼀个「区间两头」的元素:
  • 当 s[ i ] != s[ j ] 的时候:不可能是回文串, dp[ i ][ j ] = false
  • 当 s[ i ] == s[ j ] 的时候:根据长度分三种情况讨论:
    • 长度为 1 ,也就是 i == j :此时一定是回文串, dp[ i ][ j ] = true
    • 长度为 2 ,也就是 i + 1 == j :此时也一定是回文串, dp[ i ][ j ] = true
    • 长度大于 2 ,此时要去看看 [ i + 1, j - 1 ] 区间的子串是否回文: dp[ i ][ j ] = dp[i + 1][j - 1] 

#:初始化:

         因为我们的状态转移方程分析的很细致,因此无需初始化。

#:填表顺序:

        根据「状态转移方程」,我们需要「从下往上」填写每⼀行,每⼀行的顺序无所谓。

#:返回值:

        根据「状态表示和题目要求」,我们需要返回 dp 表中 true 的个数。 


C++ 算法代码 

class Solution {
public:
    int countSubstrings(string s) {
        int ret = 0;
        // 1、创建dp表
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));

        // 2、初始化

        // 3、填表
        for(int i = s.size() - 1; i >= 0; i--)
        {
            for(int j = i; j < s.size(); j++)
            {
                if(s[i] == s[j])
                    dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
                if(dp[i][j]) 
                    ret++; // 统计个数
            }
        }
        return ret;
    }
};

最长回文子串 ⭐⭐ 

5. 最长回文子串 - 力扣(LeetCode)


【题目解析】 

        与上一题一样。

【算法原理】

#:状态表示:

        为了能表示出来所有的子串,我们可以创建⼀个 n * n 的⼆维 dp 表,只用到「上三角部分」
即可。 其中, dp[i][j] 表示: s 字符串 [i, j] 的子串,是否是回文串。

#:状态转移方程:

对于回文串,我们⼀般分析⼀个「区间两头」的元素:
  • 当 s[ i ] != s[ j ] 的时候:不可能是回文串, dp[ i ][ j ] = false
  • 当 s[ i ] == s[ j ] 的时候:根据长度分三种情况讨论:
    • 长度为 1 ,也就是 i == j :此时一定是回文串, dp[ i ][ j ] = true
    • 长度为 2 ,也就是 i + 1 == j :此时也一定是回文串, dp[ i ][ j ] = true
    • 长度大于 2 ,此时要去看看 [ i + 1, j - 1 ] 区间的子串是否回文: dp[ i ][ j ] = dp[i + 1][j - 1] 

#:初始化:

        因为我们的状态转移方程分析的很细致,因此无需初始化。

#:填表顺序:

        根据「状态转移方程」,我们需要「从下往上」填写每⼀行,每⼀行的顺序无所谓。

#:返回值:

        根据「状态表示和题目要求」,我们需要返回 dp 表中 true 的个数。 


C++ 算法代码  

class Solution {
public:
    string longestPalindrome(string s) {
        int ret_max = 0;
        int begin_index = 0;
        // 1、创建dp表
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));

        // 2、初始化

        // 3、填表
        for(int i = s.size() - 1; i >= 0; i--)
        {
            for(int j = i; j < s.size(); j++)
            {
                if(s[i] == s[j])
                    dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;

                if(dp[i][j] && j - i + 1 > ret_max) 
                {
                    ret_max = j - i + 1 ;
                    begin_index = i;     
                }
            }
        }

        // 4、返回值
        return s.substr(begin_index, ret_max);
    }
};

回文串分割Ⅳ⭐⭐⭐ 

1745. 回文串分割 IV - 力扣(LeetCode)


【题目解析】 

        与上题和上上题一样。

        因为其能够将所有的字串是否是回文的信息,保存在dp表中。所以我们只需要在前述中,最后加入一个判断。

【算法原理】

#:状态表示:

        为了能表示出来所有的子串,我们可以创建⼀个 n * n 的⼆维 dp 表,只用到「上三角部分」
即可。 其中, dp[i][j] 表示: s 字符串 [i, j] 的子串,是否是回文串。

#:状态转移方程:

对于回文串,我们⼀般分析⼀个「区间两头」的元素:
  • 当 s[ i ] != s[ j ] 的时候:不可能是回文串, dp[ i ][ j ] = false
  • 当 s[ i ] == s[ j ] 的时候:根据长度分三种情况讨论:
    • 长度为 1 ,也就是 i == j :此时一定是回文串, dp[ i ][ j ] = true
    • 长度为 2 ,也就是 i + 1 == j :此时也一定是回文串, dp[ i ][ j ] = true
    • 长度大于 2 ,此时要去看看 [ i + 1, j - 1 ] 区间的子串是否回文: dp[ i ][ j ] = dp[i + 1][j - 1] 

#:初始化:

        因为我们的状态转移方程分析的很细致,因此无需初始化。

#:填表顺序:

        根据「状态转移方程」,我们需要「从下往上」填写每⼀行,每⼀行的顺序无所谓。

#:返回值:

        根据「状态表示和题目要求」,我们需要返回 dp[0][i - 1] && dp[i][j] && dp[j + 1][s.size() - 1] 循环判断。 


C++ 算法代码

class Solution {
public:
    bool checkPartitioning(string s) {
        
        // 1、创建dp表
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));

        // 2、初始化

        // 3、填表
        for(int i = s.size() - 1; i >= 0; i--)
        {
            for(int j = i; j < s.size(); j++)
            {
                if(s[i] == s[j])
                    dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
            }
        }

        // 4、返回值
        for(int i = 1; i < s.size() - 1; i++)
        {
            for(int j = i; j < s.size() - 1; j++)
            {
                if(dp[0][i - 1] && dp[i][j] && dp[j + 1][s.size() - 1])
                    return true;
            }
        }
        return false;
    }
};

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

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

相关文章

浮点型进制转换 和 与或非(逻辑短路)

正数的反码是其本身 负数的补码是其反码1 原码 十进制数据的二进制表现形式 byte b 13 1101&#xff08;13的十进制&#xff09;byte代表占存储的一个字节&#xff08;1字节等于8位&#xff09; 此时13的在存储里的形式 0000 1101 &#xff08;原码最左边0为正&#…

物联网Lora模块从入门到精通(六)OLED显示屏

一、前言 获取到数据后我们常需要在OLED显示屏上显示&#xff0c;本文中我们需要使用上一篇文章(光照与温湿度数据获取)的代码&#xff0c;在其基础上继续完成本文内容。 基础代码&#xff1a; #include <string.h> #include "board.h" #include "hal_ke…

Spring boot之WEB 开发-静态资源访问--自定义转换器--处理JSON--内容协商

Spring boot之WEB 开发-静态资源访问 官方文档 在线文档: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.develo\ping-web-applications 基本介绍 1. 只要静态资源放在类路径下&#xff1a; /static 、/public 、/resources 、/M…

2023-06-11:redis中,如何在100个亿URL中快速判断某URL是否存在?

2023-06-11&#xff1a;redis中&#xff0c;如何在100个亿URL中快速判断某URL是否存在&#xff1f; 答案2023-06-11&#xff1a; 传统数据结构的不足 当然有人会想&#xff0c;我直接将网页URL存入数据库进行查找不就好了&#xff0c;或者建立一个哈希表进行查找不就OK了。 …

【Java】数组是引用类型

【Java】数组是引用类型 Java虚拟机运行时的数据区基本类型变量与引用类型变量的区别 Java虚拟机运行时的数据区 程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址。 虚拟机栈(JVM Stack): 与方法调用相关的一些信息&#xff0c;每个方法在执行时&a…

【算法系列 | 5】深入解析排序算法之——快速排序

序言 你只管努力&#xff0c;其他交给时间&#xff0c;时间会证明一切。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记一级论点蓝色&#xff1a;用来标记二级论点 决定开一个算法专栏&#xff0c;希望能帮助大…

【日志解析】【频率分析】ULP:基于正则表达式和本地频率分析进行日志模板提取

An Effective Approach for Parsing Large Log Files 文章目录 An Effective Approach for Parsing Large Log Files1 论文出处2 背景2.1 背景介绍2.2 针对问题2.3 创新点 3 主要设计思路3.1 预处理3.2 日志事件分组3.3 通过频率分析生成日志模板 4 实验设计4.1 准确性4.2 效率…

物联网Lora模块从入门到精通(八)Lora无线通信

一、前言 在某些环境下&#xff0c;无法通过有线传输数据&#xff0c;这时候我们需要使用Lora无线通信传输数据&#xff0c;Lora无线数据传输具有低功耗、距离长的特点&#xff0c;常用于工厂内等&#xff0c;需要Lora基站。 我曾做过距离测试&#xff1a;Lora模块距离测试-物联…

【Pytest实战】pytest 基本概念及使用大全

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;不想…

Spring6-02

JdbcTemplate JdbcTemplate是Spring提供的一个JDBC模板&#xff0c;是对JDBC的封装&#xff0c;简化了JDBC代码。当然也可以不用JdbcTemplate&#xff0c;可以让Spring集成其他的ORM框架&#xff0c;例如MyBatis、Hibernate等。接下来使用JdbcTemplate完成增删改查。 环境准备…

重写并自定义console.log()输出样式

0. 背景 笔者在开发的实践过程中对于控制台内容的输出情况有一些特殊的需求&#xff0c;然而&#xff0c;普通的console.log()函数不能提供很好的支持&#xff0c;因此需要探索一些自定义的实现方式&#xff0c;以便满足开发需求&#xff0c;一些开发需求如下&#xff1a; 输…

编译详细过程与交叉编译

GCC的编译过程&#xff1a; GCC编译分为四步&#xff0c;预处理、编译、汇编、链接。具体功能如上图所示&#xff0c;我们在稍微解释一下&#xff1a; 1.预处理&#xff1a; 实现过程&#xff1a;gcc -E xxx.c -o xxx.i 目的&#xff1a;我们的c程序中除了main函数以外&…

如何在Linux中使用read命令读取用户输入?——read命令实战

前言 大家好&#xff0c;又见面了&#xff0c;我是沐风晓月&#xff0c;本文是专栏【linux基本功-基础命令实战】的第64篇文章。 专栏地址&#xff1a;[linux基本功-基础命令专栏] &#xff0c; 此专栏是沐风晓月对Linux常用命令的汇总&#xff0c;希望对你有用。 今天我们一…

实现jvm内存溢出

那么我们如何来构建一个堆内存溢出呢&#xff1f;其实很简单&#xff0c;我们只要定义一个List对象&#xff0c;然后通过一个循环不停的往List里面塞对象。因为只要Controller不被回收&#xff0c;那么它里面的成员变量也是不会被回收的。这样就会导致List里面的对象越来越多&a…

Play wright自动化测试工具该如何更加完美地使用

目录 1.1 拦截网络请求 1.2 pytest 管理用例 1.3 PO模型 1.4 API 和 UI 自动化测试融合 1.5 数据驱动 1.6 动态挑选用例执行 1.6 Allure测试报告 1.7 持续集成 1.1 拦截网络请求 网络拦截&#xff1a; 无响应 pass 中止 route.abort("aborted") 放行 route…

Hazel游戏引擎(013)Layers游戏的层级

文中若有代码、术语等错误&#xff0c;欢迎指正 文章目录 前言增加Layer后的主要类图项目相关代码项目流程效果 LayerStack类的错误 前言 此节目的 为完成008事件系统设计的第四步&#xff0c;将事件从Application传递分发给Layer层。 使引擎事件系统模块完整 Layer的理解 …

在VSCode下利用PlateFormIO开发Arduino的MicroROS遇到的一些问题

简介 我是按照鱼香ROS的教程【3.搭建PlateFormIO开发环境】进行的&#xff0c;但是在进行的过程中&#xff0c;遇到了一些问题&#xff0c;这里记录下来&#xff0c;供有同样问题的同学进行参考。其实只要你使用的板子的MCU是ESP32&#xff0c;都可以按照他这个教程进行操作。…

k8s实践之mysql集群搭建(十五)

先下载 k8s实践之mysql集群搭建资料 主从模式简介&#xff1a; 当master主服务器上的数据发生改变时&#xff0c;则将其改变写入二进制&#xff08;binlog&#xff09;事件日志文件中&#xff1b; slave从服务器会在一定时间间隔内对master主服务器上的二进制日志进行探测&am…

掌握Vue生命周期,让你的前端开发效率翻倍!

1 Vue实例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Vue实例</title><script src../vue.js></script> </head> <body><div id"root"><!-- v…

位图以及布隆过滤器

本文主要讲解哈希思想的实际应用&#xff0c;位图和布隆过滤器。 位图 讲解位图之前我们先来解答这样一道腾讯的面试题 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。【腾讯】 很多人立马就想到了用…