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 1:

Input: "babad"
Output: "bab"

Note: “aba” is also a valid answer.
Example 2:

Input: "cbbd"
Output: "bb"

方法1: expand around center

思路:

这种方法是遍历一遍枚举中心轴,在每一个可能的中心轴向两端展开。在任意时刻,如果出现两端不等的情况,可以立刻记录一下最大值并推出。注意因为回文有可能是奇数或者偶数长度,我们需要列举所有a|b|c一共五种中心点的可能性,但是可以通过同一个函数来统一查找。这个函数会自动update 两个数值:start, maxlen,在全部查找结束后返回s.substr(start, maxlen)即所求。

Complexity

Time complexity: O(n^2), 遍历中心轴O(n), 对每一个中心轴可能需要expandO(n)次。
Space complexity: O(1)

易错点:

  1. right - left - 1:字符串的长度一般都是r - l + 1这里为什么减1呢?因为循环停下来的时候左右指针都指向了第一次左右不相等的情况,长度是中间串的长度。
  2. 如果完全没有回文串,也要保证最小的返回值是1.这里因为奇数长度的检查以i,i为左右起始,保证了至少会更新maxlen到1。
class Solution {
public:
    string longestPalindrome(string s) {
        if (s.size() <= 1) return s;
        int start = 0, maxlen = 0; 
        for (int i = 0; i < s.size() - 1; i++){
            searchPalindrome(s, i, i, start, maxlen);
            searchPalindrome(s, i, i + 1, start, maxlen);
        }
        return s.substr(start, maxlen);
    }
    
    void searchPalindrome(string& s, int left, int right, int & start, int & maxlen){
        while (left >= 0 && right < s.size() && s[left] == s[right]){
            left --;
            right ++;
        }
        
        if (right - left - 1 > maxlen){
            start = left + 1;
            maxlen = right - left - 1;
        }
        return;
    }
};

方法2: dynamic programming

geeksforgeeks: https://www.youtube.com/watch?v=HBtiDHIOK9A

思路:

dp: vector<bool>dp[i][j]来记录s[i,…j] 是否是回文串。
initialization: 按照对角线来填入,也就是k = 1, 2,…,n。首先初始化所有k = 1到true,然后手动检查k = 2的情况,并更新maxlen
transfer: 从k= 3开始,每次检查以i点开始,长度为k的字符串是否回文只需要调取dp[i + 1][j - 1], 这里j = i + k - 1。如果为true并且当前s[i] == s[j]储存为true,并且更新maxlen
return: 记录一个全球最长字串发生的start 和maxlen,最后截取返回。

Complexity

Time complexity: O(n^2), 填入dp的大小为n ^ 2
Space complexity: O(n^2)

易错点

  1. j = i + k - 1:举个例子,以0 为起点,长度为3,终点是j = 3 - 0 - 1 = 2。
  2. 要保证maxlen在每一种长度的情况下都有更新。
class Solution {
public:
    string longestPalindrome(string s) {
        if (s.size() <= 1) return s;
        int n = s.size();
        vector<vector<bool>> dp(n, vector<bool>(n, false));
        int start = 0, maxlen = 1;
        // length = 1
        for(int i = 0; i < n; i++){
            dp[i][i] = true;
        }
        // length = 2
        for (int i = 0; i < n - 1; i++){
            if (s[i] == s[i + 1]){
                dp[i][i + 1] = true;
                start = i;
                maxlen = 2;
            }
        }        
        // length > 2
        for (int k = 3; k <= n; k ++){
            // 起点
            for (int i = 0; i <= n - k; i++){
                // 终点
                int j = i + k - 1;
                // 查询dp中间段
                if (dp[i + 1][j - 1] && s[i] == s[j]){
                    dp[i][j] = true;
                    if (k > maxlen) {
                        start = i;
                        maxlen = k;
                    }
                }
                //else {
                //    dp[i][j] = false;
                //}
                
            }
        }
        return s.substr(start, maxlen);
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值