力扣算法 5.最长回文子串

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

在这里插入图片描述
在这里插入图片描述

解:
对于一个字符串而言,如果它是回文串,并且长度大于2,那么将他的收尾两个字母去掉之后一定是仍然是一个回文串。例如ababa 如果已知bab是回文串,那么ababa一定是回文串,因为首尾字母都是a
因此,可以使用动态规划解决本体,使用P(i,j)表示字符串s的第i到j个字母组成的串s[i:j] 是否为回文串
这里包括两种可能性

  1. s[i,j]本身不是一个回文串
  2. i>j,此时s[i,j]不合法
    那么我们就可以写出动态规划的状态转移方程
    在这里插入图片描述

也就是说,只有s[i+1:j-1]是回文串,并且s的第i和j个字母相同时,s[i:j]才会是回文串

所提到的都是建立在子串长度大于2的前提之上的,还需要考虑动态规划中的边界条件,也就是子串的长度为1或者2.对于长度为1的子串,它显然是一个回文串;对于长度为2的子串,只要它的两个字母相同,他就是一个回文串。因此我们可以写出动态规划的边界条件。

在这里插入图片描述根据这个思路我们可以完成动态规划,最终的答案即为所有P(i,j)=true 中的j-i+1(子串长度)的最大值
需要注意的是,在状态转移方程中,我们是从长度较短的字符串向长度较长的字符串进行转移的,因此需要注意动态规划的循环顺序。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

动态规划法 C++

class Solution {
    
    
public:
    string longestPalindrome(string s) {
    
    
        int n=s.size();//如果小于2的话直接返回
        if(n<2){
    
    
            return s;
        }
        int maxLen =1;
        int begin=0;
        vector<vector<int>> dp(n,vector<int>(n));// dp[i][j] 表示 s[i..j] 是否是回文串
        //声明了一个名为dp的二维动态数组,它有n行n列,每个元素都是int类型。

        //vector<int>(n) 部分创建一个包含 n 个元素的一维整数向量,并将每个元素初始化为零。(列)  vector<vector<int>> 部分创建一个包含 n 行的二维向量,其中每一行都是由 vector<int>(n) 创建的一维向量的副本。
        for(int i=0;i<n;i++)
        {
    
    
            dp[i][i]=true;
        }
        //递推开始
        //首先枚举子串长度
        for(int L=2;L<=n;L++)
        {
    
    
            for(int i=0;i<n;i++)//枚举左边界,左边界的上限设置可以宽松一些
            {
    
    
                int j=L+i-1;//由L和i可以确定右边边界,也就是j-i+1=L
                if(j>=n)//如果右边界越界,那么直接退出循环
                {
    
    
                    break;
                }
                if(s[i]!=s[j])
                {
    
    
                    dp[i][j]=false;
                }else{
    
    
                    if(j-i<3)
                    {
    
    
                        dp[i][j]=true;
                    }else{
    
    
                        dp[i][j]=dp[i+1][j-1];
                    }
                }
                if(dp[i][j]&&j-i+1>maxLen){
    
    
                    maxLen=j-i+1;
                    begin=i;
                }
              
            }
        }
        return s.substr(begin,maxLen);
        //substr() 方法用于提取字符串的一部分,从指定的索引 (begin) 开始,并持续指定的字符数 (maxLen)。
    }
};

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zhangyuanbonj/article/details/129923151