刷题之动态规划-回文串

前言

大家好,我是jiantaoyab,开始刷动态规划的回文串类型相关的题目

动态规划5个步骤

  1. 状态表示 :dp数组中每一个下标对应值的含义是什么>dp[i]表示什么
  2. 状态转移方程: dp[i] 等于什么
  3. 1 和 2 是动态规划的核心步骤,第三步是初始化,保证填表的时候不越界
  4. 填表顺序:为了保证填写当前状态的时候,所需要的状态已经计算过
  5. 返回值

回文子串

题目分析

代码

cpp 复制代码
class Solution {
public:
    int countSubstrings(string s) {
      int n = s.size();
      int ret = 0;
      vector<vector<bool>> dp(n, vector<bool>(n));
      for(int i = n - 1; i >= 0; i--)
      {
        for(int j = i; j < n; j++) // i <= 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;
    }
};

最长回文子串

代码

动态规划版本

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

中心探测法

cpp 复制代码
class Solution {
public:
    string longestPalindrome(string s) {
     string RetStr="";
     for(int i=0;i<s.size();i++)
     {
         //回文串为奇数
         int left=i-1;
         int right=i+1;
         while(left>=0&&right<s.size()&&s[left]==s[right])
         {
             left--;
             right++;
         }
         if(RetStr.size()<right-left-1)
         {
             //babad
             //01234  letf=-1 i=1  right=3
             RetStr=s.substr(left+1,right-left-1);
         }
        //回文串为偶数
         left=i;
         right=i+1;
           while(left>=0&&right<s.size()&&s[left]==s[right])
         {
             left--;
             right++;
         }
          if(RetStr.size()<right-left-1)
         {
             
             RetStr=s.substr(left+1,right-left-1);
         }

     }
        return RetStr;
    }
};

分割回文串 IV

代码

cpp 复制代码
class Solution {
public:
    bool checkPartitioning(string s) {
      int n = s.size();
      vector<vector<bool>> dp(n, vector<bool>(n));
      int count = 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;
        
        }
      }

      //枚举第二个字符串的起始位置和结束位置
      for(int i = 1; i < n - 1; i++) //前后留一个字符给第一个字符串
      {
        for(int j = i; j < n - 1; j++)//结束位置从i开始到n - 1
        {
            if(dp[0][i - 1] && dp[i][j] && dp[j + 1][n - 1] ) return true;
        }
      }
      return false;
    }
};

分割回文串 II

题目分析

代码

cpp 复制代码
class Solution {
public:
    int minCut(string s) {
      int n = s.size();
      vector<vector<bool>> is_pal(n, vector<bool>(n));
      int ret = 0;
      //把所有子串是不是回文串放到is_pal中
      for(int i = n - 1; i >= 0; i--)
      {
        for(int j = i; j < n; j++)
        {
          if(s[i] == s[j]) is_pal[i][j] = i + 1 < j ? is_pal[i + 1][j - 1] : true;
        }
      }
      vector<int> dp(n, INT_MAX);
      for(int i = 0; i < n; i++)
      {
        if(is_pal[0][i]) dp[i] = 0;
        // [0, i] 不是回文串
        else
        {
          for(int j = 1; j <= i; j++)
          {
            if(is_pal[j][i]) dp[i] = min(dp[i], dp[j - 1] + 1);
          }
        }
      }
      return dp[n - 1];
    }
};

最长回文子序列

题目分析

代码

cpp 复制代码
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--)
      {
        dp[i][i] = 1; // i == j
        for(int j = i + 1; j < n; j++)
        {
          if(s[i] == s[j])
          {
            if(i + 1 == j) dp[i][j] = 2;
            else if(i + 1 < j) dp[i][j] = dp[i + 1][j - 1] + 2;
          }
          else
          {
            dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]);
          }

        }
      }
      return dp[0][n - 1];
    }
};

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

题目分析

cpp 复制代码
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] = min(dp[i + 1][j] + 1, dp[i][j - 1] + 1);
          }
        }
      }
      return dp[0][n - 1];
    }
};
相关推荐
WolfGang00732120 分钟前
代码随想录算法训练营 Day37 | 动态规划 part10
算法·动态规划
baizhigangqw23 分钟前
启发式算法WebApp实验室:从搜索策略到群体智能的能力进阶(二)
算法·启发式算法·web app
alphaTao23 分钟前
LeetCode 每日一题 2026/4/13-2026/4/19
算法·leetcode·职场和发展
灵智实验室28 分钟前
PX4姿态解算技术详解(四):姿态更新/递推与共锥补偿
算法·无人机·px 4
良木生香29 分钟前
【C++初阶】C++编程基石:编码表&&STL的入门指南
c语言·开发语言·数据结构·c++·算法
秋935 分钟前
学霸圈公认的 10 种高效学习习惯:从低效到顶尖的底层逻辑
人工智能·学习·算法
极简车辆控制1 小时前
泵控式电液主动悬架系统分层控制研究_论文复现
算法·汽车
扶苏xw1 小时前
【分组背包】
算法·动态规划
李兆龙的博客1 小时前
从一到无穷大 #68 Agent Memory 全景:大模型智能体记忆机制的形态、动态与前沿
大数据·人工智能·算法
cwplh2 小时前
平衡树学习笔记
数据结构·笔记·学习·算法