【算法】【动规】回文串系列问题

2023-12-25 07:20

本文主要是介绍【算法】【动规】回文串系列问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 跳转汇总链接
    • 3.1 回文子串
    • 3.2 最长回文子串
    • 3.3 分割回文串 IV
    • 3.4 分割回文串II(hard)


跳转汇总链接

👉🔗动态规划算法汇总链接


3.1 回文子串

🔗题目链接

给定一个字符串 s ,请计算这个字符串中有多少个回文子字符串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

  1. 状态表示
    • dp[i][j] 表示字符串 s 中以 i 位置开头 j 位置结尾的子串,是否是回文。
  2. 状态转移方程
    • 分析 dp 表,要判断 [i, j] 位置的子串是否为回文,首先要根据 s[i] 和 s[j] 的大小判定,具体如下:

      s[i] != s[j], false
      s[i] == s[j], i == j, truei + 1 == j, truej - i > 1, s[i+1][j-1] == true, trues[i+1][j-1] == false, false
      
  3. 初始化
    • 这里主要是[i+1][j-1] 可能会超出需要范围,但是有个隐含条件 i <= j,可以在 for 循环中控制,所以不需要初始化。
  4. 填表顺序
    • 填写 dp[i][j],需要有 [i+1] 和 [j-1],故二维数组从下往上填写。
  5. 返回值
    • dp 中的 true 的出现次数。

🐎代码如下:

class Solution {
public:int countSubstrings(string s) {int n = s.size();vector<vector<bool>> dp(n, vector<bool>(n));int ret = 0;for(int i = n - 1; i >= 0; i--){for(int j = i; j < n; j++){// 默认都是 false,只需要处理 true 的位置if(s[i] == s[j])dp[i][j] = i + 1 < j ? dp[i+1][j-1] : true;if(dp[i][j])ret++;}}return ret;}
};

3.2 最长回文子串

🔗题目链接

给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

如上题分析,写 dp 方程。

在 dp[i][j] 且满足基本约束时,找到 len(即 j - i + 1)的最大值,
同时,由于 dp 表是从下往上(从后往前)填的,正好更新 begin。

🐎代码如下:

class Solution {
public:string longestPalindrome(string s) {int n = s.size();int len = 1, begin = 0;vector<vector<bool>> dp(n, vector<bool>(n));for(int i = n - 1; i >= 0; i--){for(int j = i; j < n; 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 > len)len = j - i + 1, begin = i;}}return s.substr(begin, len);}
};

3.3 分割回文串 IV

🔗题目链接

给你一个字符串 s ,如果可以将它分割成三个 非空 回文子字符串,那么返回 true ,否则返回 false 。
当一个字符串正着读和反着读是一模一样的,就称其为 回文字符串 。

还是照上述方法,生成 dp 表,记录是否为回文子串,进行数据预处理;

再将字符分成三部分,依次遍历,如果 相应位置的 dp 值为 true,就可以直接返回啦。

🐎代码如下:

class Solution {
public:bool checkPartitioning(string s) {int n = s.size();// 1. 预处理:子串是否是回文vector<vector<bool>> dp(n, vector<bool>(n));for(int i = n - 1; i >= 0; i--)for(int j = i; j < n; j++)if(s[i] == s[j])dp[i][j] = i+1 < j ? dp[i+1][j-1] : true;// 2. 字符串分成三段,枚举就好了// [0, i) [i, j) [j, n)for(int i = 1; i < n - 1; i++)  // i 是第二段的起始for(int j = i + 1; j < n; j++)  // j 是第三段的起始if(dp[0][i-1] && dp[i][j-1] && dp[j][n-1])return true;return false;}
};

3.4 分割回文串II(hard)

🔗题目链接

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。

同样先预处理数据,方便判断子串是否是回文串;

剩下的分析方法与 1.4 单词拆分题 一样:

  • dp[i] 表示 s[0, i] 位置上的最长字串的最小分割次数;
  • 当分析 dp[i] 的时候,需要将[0, i] 分成两部分:
    • 首先是离 i 最近的 [j, i],找到能满足是回文的 j,

    • 再找 [0, j-1] 的最小分割次数,正是和状态表示一样,于是有

      dp[i], [0, i] 是回文,0[0, i] 不是回文,有 0 < j <= i,[j, i] 是回文,求 min(dp[j]+1)[j, i] 不是回文,不考虑
      

🐎代码如下:

class Solution {
public:int minCut(string s) {int n = s.size();// 1. 预处理:子串是否是回文vector<vector<bool>> sub(n, vector<bool>(n));for(int i = n - 1; i >= 0; i--)for(int j = i; j < n; j++)if(s[i] == s[j])sub[i][j] = i+1 < j ? sub[i+1][j-1] : true;// 2. 分割,是另一个dp问题咯~vector<int> dp(n, 0x3f3f3f3f);for(int i = 0; i < n; i++){if(sub[0][i]) dp[i] = 0;elsefor(int j = 1; j <= i; j++)if(sub[j][i])dp[i] = min(dp[j - 1] + 1, dp[i]);}return dp[n-1];}
};

🥰如果本文对你有些帮助,欢迎👉 点赞 收藏 关注,你的支持是对作者大大莫大的鼓励!!(✿◡‿◡) 若有差错恳请留言指正~~


这篇关于【算法】【动规】回文串系列问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/534665

相关文章

MySQL 设置AUTO_INCREMENT 无效的问题解决

《MySQL设置AUTO_INCREMENT无效的问题解决》本文主要介绍了MySQL设置AUTO_INCREMENT无效的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录快速设置mysql的auto_increment参数一、修改 AUTO_INCREMENT 的值。

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Java死锁问题解决方案及示例详解

《Java死锁问题解决方案及示例详解》死锁是指两个或多个线程因争夺资源而相互等待,导致所有线程都无法继续执行的一种状态,本文给大家详细介绍了Java死锁问题解决方案详解及实践样例,需要的朋友可以参考下... 目录1、简述死锁的四个必要条件:2、死锁示例代码3、如何检测死锁?3.1 使用 jstack3.2

解决JSONField、JsonProperty不生效的问题

《解决JSONField、JsonProperty不生效的问题》:本文主要介绍解决JSONField、JsonProperty不生效的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录jsONField、JsonProperty不生效javascript问题排查总结JSONField

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos

Java中JSON格式反序列化为Map且保证存取顺序一致的问题

《Java中JSON格式反序列化为Map且保证存取顺序一致的问题》:本文主要介绍Java中JSON格式反序列化为Map且保证存取顺序一致的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录背景问题解决方法总结背景做项目涉及两个微服务之间传数据时,需要提供方将Map类型的数据序列化为co

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复