leetcode:5. 最长回文子串

题目来源

题目描述

在这里插入图片描述

class Solution {
public:
    string longestPalindrome(string s) {
     
    }
};

题目解析

区间型动态规划

(1)定义状态

  • dp[i][j]表示字符串s[i, j]区间的子串是否是一个回文串。

(2)推导状态转移方程

对于区间[i][j],有两种情况

  • 如果 s [ i ] ! = s [ j ] s[i] != s[j] s[i]!=s[j],那么区间 [ i . . . j ] [i...j] [i...j]一定不是回文子串,即 d p [ i ] [ j ] = f a l s e dp[i][j] = false dp[i][j]=false
  • 如果 s [ i ] = = s [ j ] s[i] == s[j] s[i]==s[j],有下面三种情况:
    • 情况一:下标 i i i j j j相同,同一个字符当然是回文子串,比如a
    • 情况二:下标 i i i j j j相差为1,也是回文子串,比如aa
    • 情况三:下标 i i i j j j大于1的时候,区间 [ i . . . j ] [i...j] [i...j]是不是回文子串取决于区间 [ i + 1... i − 1 ] [i+1...i-1] [i+1...i1]。即 d p [ i ] [ j ] = = d p [ i − 1 ] [ j − 1 ] dp[i][j] == dp[i-1][j-1] dp[i][j]==dp[i1][j1]
  • 要求最长回文子串,用遍历ans表示最长的回文子串,变量max_len 表示最长回文子串的长度
    • d p [ i ] [ j ] = t r u e dp[i][j] = true dp[i][j]=true时,当前回文子串的长度是curr_len = j - i
    • 当curr_len> max_len 时,更新max_len和ans

(3)初始情况与边界情况

  • d p [ i ] [ j ] dp[i][j] dp[i][j]初始化为false

(4)遍历顺序

  • dp[i + 1][j - 1] 在 dp[i][j]的左下角

在这里插入图片描述

  • 所以一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的
class Solution {
public:
    string longestPalindrome(string s) {
        int len = s.size();
        std::vector<std::vector<int>> dp(len, std::vector<int>(len, false));

        std::string ans; int max_len  = 0;
        for(int i = len - 1; i >= 0; i--){
            for (int j = i; j < len; ++j) {
                if(s[i] == s[j]){
                    int curr_len = j - i;
                    if(curr_len <= 1 || dp[i + 1][j - 1]) {
                        dp[i][j] = true;
                        if(curr_len > max_len ){
                            max_len  = curr_len;
                            ans = s.substr(i, curr_len + 1);
                        }
                    }
                }
            }
        }

        return ans;
    }
};

枚举

枚举字符串 s 中的每一位,作为回文串的中心点,左右进行扩展,直到达到边界或者不满足回文串定义为止。

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, 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) {
                start = left1;
                end = right1;
            }
            if (right2 - left2 > end - start) {
                start = left2;
                end = right2;
            }
        }
        return s.substr(start, end - start + 1);
    }
};

马拉车算法

类似题目

判断是不是回文

题目思路
leetcode:9. 判断整数num是不是回文数 Palindrome Number递归;反转全部的数(小心溢出);反转一半的数;转成字符串再判断; 双指针:取出最高位&最低位;
leetcode:234. 判断链表是不是回文链表 Palindrome Linked List使用栈;反转整个链表比较;反转半个链表
leetcode:125. 验证字符串str是不是回文串 Validate Palindrome递归,双指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值