LeetCode - 5. Longest Palindromic Substring

本文介绍了三种解决LeetCode 5题——最长回文子串的方法:暴力求解、动态规划和Manacher's Algorithm。暴力求解通过检查每个位置为中心的奇偶回文,动态规划则利用状态转移方程dp[i][j]来确定子串是否为回文,而Manacher's Algorithm是一种更高效的解决方案,但实现较为复杂。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Longest Palindromic Substring

解法一 Brute Force

遍历每个位置,并查看是否存在以这个位置为中心的(奇和偶)回文。

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.empty()) return s;
        int mx=1, start=0;
        for(int i=0;i<s.size()-1;i++){
            updateMx(s, i, i, start, mx);   // odd
            updateMx(s, i, i+1, start, mx); // even
        }
        return s.substr(start, mx);
    }
    void updateMx(string s, int l, int r, int& start, int& mx){
        while(l>=0 && r<s.size() && s[l]==s[r]){
            l--; r++;
        }
        if(mx<r-l-1){   // at s[l]!=s[r]
            mx = r-l-1;
            start=l+1;
        }
    }
};
class Solution {
    private int low, maxLen;
    public String longestPalindrome(String s) {
        int len = s.length();
        if(len<2) return s;
        for(int i=1;i<len;i++){
            helper(s, i, i);
            helper(s, i-1, i);
        }
        return s.substring(low, low+maxLen);
    }
    public void helper(String s, int l, int r){
        while(l>=0 && r<s.length() && s.charAt(l)==s.charAt(r)){
            l--;
            r++;
        }
        if(maxLen < r-l-1){
            maxLen = r-l-1;
            low = l+1;
        }
    }
}

变形 no helper function

怎么样generalize奇偶的情况?
奇偶的区别其实就在中间位置,奇:中间位只出现一次;偶:中间位出现了两次
那么我们从中间(一位或两位)的两边开始check equality不就行了嘛?

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.empty()) return s;
        int mx=1, start=0;
        for(int i=0;i<s.size();){
            int l=i, r=i;
            while(r<s.size()-1 && s[r]==s[r+1]) r++;
            i=r+1;
            while(l>0 && r<s.size()-1 && s[l-1]==s[r+1]){
                l--; r++;
            }
            if(mx<r-l+1){ // at s[l]==s[r]
                mx = r-l+1;
                start = l;
            }           
        }
        return s.substr(start, mx);
    }
};

解法二 DP

上面?这种方法是以每个位置为中心出发思考的,那么我们换一个思路
问题问:最长的palindrome -> 那么我们能不能找到所有的palindrome先 -> 我们能不能找到所有的string先
再回到问题,有了所有的strings怎么确定是不是palindrome? [str(i, j) means string from position i to j]
确定str(i, j)是不是palindrome,我们需要compare 
s[i] == s[j]
s[i+1] == s[j-1]
s[i+2] == s[j-2]

......
确定str(i+1, j-1)是不是palindrome,我们需要compare 
s[i+1] == s[j-1]
s[i+2] == s[j-2]

s[i+3] == s[j-3]
......
聪明的小伙伴一定嗅到了DP的味道:str(i, j) = ( s[i] == s[j] && str(i+1, j-1) )

如何遍历呢?
从之前得到的等式中,我们发现:
在处理str(i, j)的时候,
j-1已经ready了 -> j 在最外层从小至大遍历
i的遍历顺序无所谓,因为是基于j-1的i

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.empty()) return "";
        int mx=1, start=0, n=s.size();
        bool dp[n][n]={false};
        for(int j=0;j<n;j++){
            dp[j][j] = true;
            for(int i=0;i<j;i++){
                if(s[i]==s[j] && (i==j-1 || dp[i+1][j-1])){
                    dp[i][j] = true;
                    if(mx<j-i+1){
                        mx = j-i+1;
                        start = i;
                    }                   
                }
            }
        }
        return s.substr(start, mx);
    }
};

解法三 Manacher's Algorithm

[跟我一样害怕这个algorithm的小伙伴快来握个手,看了好几遍都是自以为懂了~]
另开一篇专门讲这个吧~~~ Manacher‘s Algorithm 马拉车算法

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.empty()) return "";
        string t = "$#";
        for(char c: s){
            t += c;
            t += '#';
        }
        vector<int> lens(t.size(), 0);
        int mx=0, id=0, resLen=0, resCenter=0;
        for(int i=1;i<t.size();i++){
            lens[i] = mx > i ? min(lens[2*id-i], mx-i):1;
            while(t[i+lens[i]]==t[i-lens[i]]) lens[i]++;
            if(mx<i+lens[i]){
                mx = i+lens[i];
                id = i;
            }
            if(resLen<lens[i]){
                resLen = lens[i];
                resCenter = i;
            }
        }
        return s.substr((resCenter - resLen) / 2, resLen - 1);
    }
};

What I can get from this question

1.Longest String can be represented as [1. the start point; 2. the length]
2.if (s[l] == s[r]) end up with s[l] != s[r]
   if (s[l-1] == s[r+1]) end up with s[l] == s[r]
3. Error: runtime error: variable length array bound evaluates to non-positive value 0
   bool dp[n][n] = {false} <-  n cannot be zero

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值