【LeetCode】5. Longest Palindromic Substring

5. Longest Palindromic Substring

介绍

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

Example:

Input: "cbbd"

Output: "bb"

解答

方法1: 动态规划

利用一个辅助数组help,help[i][j]记录着子字符串s[i]~s[j]是否是回文。如果是回文则为1,不是回文则为0.

所以递推关系式是:
                        1  s[i] == s[j] 且 help[i+1][j-1] == 1
        help[i][j] =    1  s[i] == s[j] 且 j == i+1
                        0  其他

在自下而上填写动态规划数组的时候,我们记录下最长的回文子字符串就可以了。

class Solution {
public:
    // 最长回文子字符串
    // 做法1:用DP做 时间复杂度 O(N^2),空间复杂度O(N^2)
    string longestPalindrome(string s) {
        if(s.size() <= 1)  return s;
        vector<vector<int>> help(s.size(),vector<int>(s.size(),1));

        int maxSize = 1;
        string res = s.substr(0,1);

        for(int i = 0; i < s.size(); ++i)
            help[i][i] == 1;

        for(int i = s.size()-1; i >= 0; --i)
        {
            for(int j = i+1; j < s.size(); ++j)
            {
                help[i][j] = ((s[i] == s[j]) && (help[i+1][j-1]));
                if(help[i][j] && j-i+1 > maxSize)
                {
                    maxSize = j-i+1;
                    res = s.substr(i,maxSize);
                }
            }
        }
        return res;
    }
};

方法2

对于回文子字符串的回文序列一定存在一个对称轴,沿着对称轴两边扩展是完全相同的。
对于奇数个数的回文序列,对称轴一定在最中间节点。如aba的对称轴就是a

对于偶数个数的回文序列,对称轴一定是在中间的两个节点。如abba的对称轴就是bb,并且两个节点的值也是相同的。

我们就是先确定可能的回文子字符串的中心点,然后往两端扩展,求取以此中心点的最长回文子字符串。按照回文子字符串的奇偶性不同,共有N-1+N = 2N-1个中心店。从这些中心点展开寻找最长的回文子字符串即可。

时间复杂度为O(N^2)。

class Solution {
public:
    string longestPalindrome(string s)
    {
        if(s.size() <= 1)   return s;

        int maxSize = 1;
        string res = s.substr(0,1);

        for(int i = 0; i < s.size()-1; ++i)
        {
            string temp = getPalindrome(s,i,i);
            if(temp.size() > res.size())
                res = temp;
            temp = getPalindrome(s,i,i+1);
            if(temp.size() > res.size())
                res = temp;
        }
        string temp = getPalindrome(s,s.size()-1,s.size()-1);
            if(temp.size() > res.size())
                res = temp;
        return res;
    }
 private:   
    string getPalindrome(string s,int left,int right)
    {
        while(left >= 0 && right < s.size() &&  s[left] == s[right])
        {
            --left,++right;
        }
        return s.substr(left+1,right-left-1);
    }
};

方法3

方法3十分巧妙,它是确保先寻找可能的回文中心,然后再往两端扩展,查找相应的回文子字符串。时间复杂度应该为O(N)~O(N^2)

class Solution {
public:
    // 做法3:时间复杂度为O(N) ~ O(N^2), 3ms
    string longestPalindrome(string s)
    {
        if(s.size() <= 1)   return s;
        int min_start = 0, max_len = 1;
        for(int i = 0; i < s.size(); )
        {
            int j = i, k = i;
            while(k < s.size()-1 && s[k+1] == s[k])     {++k;}    //跳过重复元素
            i = k+1;
            while(j > 0 && k < s.size()-1 && s[j-1] == s[k+1])     {--j,++k;}
            int new_len = k-j+1;
            if(new_len > max_len)
            {
                min_start = j;
                max_len = new_len;
            }
        }
        return s.substr(min_start,max_len);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值