最长回文子串(动态规划) 力扣 c++

5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
解法1:动态规划,时间复杂度O(n^2)
空间复杂度O(n^2)
思路:我们枚举出字符串的所有子串,并判断这个子串是否是回文串,dp[i][j]记录下标为i和下标为j的字串是都是回文字子串。当回文串的长度为1时,它就是回文子串dp[i][j]=true,i==j,当回文串的长度为2时,dp[i][j]=(s[i]==s[j]); 当回文串>2时,dp[i][j]的值就与上一个状态和s[i][j]有关系了,具体代码如下所示:

class Solution {
public:
    string longestPalindrome(string s) {
        int n=s.size();
        vector<vector<bool>>dp(n,vector<bool>(n));
        //用于存储最长回文子串
        string ans="";
        //回文串的可能长度
        for(int l=0;l<n;l++)
        {
            //从每一个位置上枚举起点
            for(int i=0;i+l<s.size();i++)
            {
                int j=i+l;//计算终点
                if(l==0)
                    dp[i][j]=true;
                else if(l==1)
                    dp[i][j]=(s[i]==s[j]);
                else
                {
                    dp[i][j]=(s[i]==s[j]&&dp[i+1][j-1]);
                }
                if(dp[i][j]&&l+1>ans.length())
                    ans=s.substr(i,l+1);
            }
        }
        return ans;
    }
};

解法2:用扩展方法,由中心点向两边扩展。时间复杂度O(n^2),空间复杂度O(1)。
思路:回文串的长度可能为奇数也可能为偶数,我们选取回文串的中心字串时应该考虑用一个子串作为中心点和两个子串作为中心点,然后向两边延伸,取出最长的长度即可,代码如下:

class Solution {
public:
    pair<int,int> expandAroundCenter(const string& s,int left,int right)
    {
        while(left>=0&&right<s.size()&&s[left]==s[right])
        {
            left--;
            right++;
        }
        return {left+1,right-1};
    }
    string longestPalindrome(string s) {
        int start=0;
        int end=0;
        for(int i=0;i<s.size();i++)
        {
            auto [left1,right1]=expandAroundCenter(s,i,i);
            auto[left2,right2]=expandAroundCenter(s,i,i+1);
            if(right1-left1>end-start)
            {
                end=right1;
                start=left1;
            }
            if(right2-left2>end-start)
            {
                end=right2;
                start=left2;
            }
        }
        return s.substr(start,end-start+1);
    }
};

你可能感兴趣的:(动态规划,leetcode,c++)