当前位置: 首页 > news >正文

动规:回文串问题

目录

No.1 回文子串

No.2 最长回文子串

No.3 分隔回文串IV

No.4 分割回文串II

No.5 最长回文子序列

No.6 让字符串成为回文串的最少插入次数


No.1 回文子串

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

题目描述:

具有不同开始位置或者结束位置的子串,即使是由相同字符组成,也视作不同的回文子串。

子串也要求连续性。

返回回文子串数量。

思路:

ps:可以用更优的 中心扩展算法 or 马拉车算法 来解决这道题。这里只介绍动规。

我们可以通过dp,以n方级别复杂度将所有的子串是否回文的信息,保存在dp表里面。

创建二维dp表,i表示起始位置,j从i开始往后遍历。

s[i]==s[j]后的细分判断顺序很好的避免了越界

回文串的填表顺序有点不同,二维表的填表顺序应该是从下往上因为dp[i][j]需要考虑dp[i+1][j-1]

最后返回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) {if (s[i] == s[j])dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;if (dp[i][j])++ret;}}return ret;}
};

No.2 最长回文子串

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

思路和上一题一致,填表过程中更新最长回文子串的起始位置和大小

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

No.3 分隔回文串IV

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

思路:
暴力:将字符串分成三个部分的所有情况都枚举,判断有没有全都是回文的。

转成dp也很好想

class Solution {
public:bool checkPartitioning(string s) {int n=s.size();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;}}for(int i=1;i<n-1;++i){for(int j=i;j<n-1;++j){if(dp[0][i-1]&&dp[i][j]&&dp[j+1][n-1])return true;}}return false;}
};

No.4 分割回文串II

132. 分割回文串 II - 力扣(LeetCode)

思路:

既然已经知道我们可以通过dp表将任何区间的回文情况存好,那么这题就相当于在问,将原数组分成区间,让区间都是true的同时数量最少。无非就是判断区间内能不能符合子串,有点类似单词划分那题。

因为要求min,初始化所有值为INT_MAX

class Solution {
public:int minCut(string s) {int n=s.size();vector<vector<bool>> isPal(n,vector<bool>(n));for(int i=n-1;i>=0;--i){for(int j=i;j<n;++j){if(s[i]==s[j])isPal[i][j]=i+1<j?isPal[i+1][j-1]:true;}}vector<int> dp(n,INT_MAX);for(int i=0;i<n;++i){if(isPal[0][i])dp[i]=0;else{for(int j=1;j<=i;++j){if(isPal[j][i])dp[i]=min(dp[i],dp[j-1]+1);}}}return dp[n-1];}
};

No.5 最长回文子序列

516. 最长回文子序列 - 力扣(LeetCode)

子序列,和前面的子串不一样了。

回文:二维表存储?i~j存储回文信息?和之前不一样,子序列不要求连续。那么这里我们选择dp[i][j]表示i~j内部最长子序列长度。回文判断:每次往两边扩展。

子序列:二维表[i][j]表示i~j区间内的最长回文子序列长度

填表顺序从下到上,从左到右

初始化将主对角上的值设置为1,因为dp值表示区间内最大子序列长度

class Solution {
public:int longestPalindromeSubseq(string s) {int n=s.size();vector<vector<int>> dp(n,vector<int>(n));for(int i=n-1;i>=0;--i){//i==jdp[i][i]=1;//从i+1开始遍历,融合相等的另外两种分支for(int j=i+1;j<n;++j){if(s[i]==s[j])dp[i][j]=dp[i+1][j-1]+2;else dp[i][j]=max(dp[i+1][j],dp[i][j-1]);}}return dp[0][n-1];}
};

No.6 让字符串成为回文串的最少插入次数

1312. 让字符串成为回文串的最少插入次数 - 力扣(LeetCode)

需要二维表分区间讨论

不等时,分别向左右讨论

class Solution {
public:int minInsertions(string s) {int n=s.size();vector<vector<int>> dp(n,vector<int>(n));for(int i=n-1;i>=0;--i){for(int j=i+1;j<n;++j){if(s[i]==s[j])dp[i][j]=dp[i+1][j-1];else dp[i][j]=1+min(dp[i][j-1],dp[i+1][j]);}}return dp[0][n-1];}
};

回文串的问题可以转换成区间讨论的问题,这有利于我们确定最重要的状态表示。( •̀ ω •́ )✧

此篇完。

http://www.dtcms.com/a/423451.html

相关文章:

  • PostgreSQL WAL 日志发展史 - pg7
  • 商丘企业网站建设团队网站设计的内容以及步骤
  • 网站域名所有人wordpress 子域名
  • ListenHub:AI播客平台,一句话生成播客
  • 知名的媒体发稿代理有哪些
  • PyTorch nn.Linear 终极详解:从零理解线性层的一切(含可视化+完整代码)
  • 大型企业级金融信贷平台需求报告
  • 【算法】小点:List.remove
  • 文件扩展名.js .jsx .ts .tsx区别(JavaScript扩展名、React扩展名、TypeScript扩展名)
  • MySQL 在金融系统中的应用:强一致性与高可用架构实战
  • 销售型网站营销目标查网址是否安全
  • 媒体发稿平台如何选
  • 靠谱的综合门户媒体发稿如何选
  • 学习:uniapp全栈微信小程序vue3后台(29)
  • 装修设计网站排名新浪短网址链接
  • kali 01——安装及简要介绍
  • 宁夏政务网站建设标准wordpress是瀑布流吗
  • 烟台 网站建设中国广告在国外投放案例
  • OpenAI秘密测试ChatGPT安全路由,情感对话触发GPT-5严格审查
  • 赋能制造新质生产力:制造业专用低代码平台选型指南(2025)
  • 智慧工地系统:建筑行业数字化转型的核心趋势,集成云计算、物联网、大数据等技术,构建覆盖施工全周期的智能化管理体系。
  • 做一个网站需要多少人权威的手机网站制作
  • Flink 有状态与时间敏感流处理从 Concepts 到 API 实战
  • UNIX下C语言编程与实践11-UNIX 动态库显式调用:dlopen、dlsym、dlerror、dlclose 函数的使用与实例
  • 【形宙数字】Pupil Neon VR|AR|XR虚拟现实眼动追踪系统-眼动仪-视线追踪-生理心理学-虚拟模拟
  • JupyterLab+PyTorch:LoRA+4-bit量化+SFT微调Llama 4医疗推理应用|附代码数据
  • python-格式化输入输出
  • 【Dogfight论文复现】无人机视频中检测无人机的目标检测模型
  • 北京矿建建设集团有限公司 网站谷歌seo服务公司
  • 食品行业数字化转型实战:工艺优化解决方案中的四大核心模块详解