[Leetcode] 5. Longest Palindromic Substring 解题报告

本文介绍了四种不同的算法来寻找给定字符串中的最长回文子串,包括暴力枚举法、动态规划法、中心展开法及Manacher算法,并提供了动态规划法与中心展开法的具体实现代码。

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

题目

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、暴力枚举法:两种循环分别枚举每种子字符串,然后再用O(n)的时间复杂度判断该子字符串是否是回文。暴力枚举法经过优化后虽然可以按照子字符串的长度递减次序进行枚举(这样一旦发现回文串就可以立即终止并返回),但是其时间复杂度依然高达O(n^3),空间复杂度则为O(1)。

2、动态规划法:设dp[i][j]表示从索引i到索引j之间的子字符串是否是回文串,则递推公式为:dp[i][j] = (s[i] == s[j]) && (j - i <= 2 || dp[i + 1][j - 1])。注意到计算dp[i][j]则必须首先知道dp[i+1][j-1]的值,所以我们可以让j作为外循环,其值从小到大依次递增。动态规划的时间复杂度是O(n^2),空间复杂度是O(n^2)。

3、中心展开法:尽管动态规划法表现的特别优雅,但是针对该题目,它仍然不是最优解法,因为中心展开法可以在保证时间复杂度为O(n^2)的情况下,将空间复杂度降为O(1)。其基本思路是:对字符串中的每个字符,试图计算以它为中心的最长回文串(注意需要分别考虑回文串长度为奇数和偶数两种情况)。

4、Manacher算法:该算法的时间复杂度和空间复杂度都可以做到O(n),可以在网上搜索参考具体做法。但是由于该算法相对比较复杂,个人觉得在面试的时候如果能完整写出动态规划法和中心展开法,就足以让面试官放你过关了。


代码

动态规划法:

class Solution {
public:
    string longestPalindrome(string s) {
        int length = s.length();
        if(length == 0)
            return "";
        int max_length = 0;
        string answer;
        vector<vector<bool>> dp(length, vector<bool>(length, false));
        for(int j = 0; j < length; ++j)
        {
            for(int i = 0; i <= j; ++i)
            {
                dp[i][j] = (s[i] == s[j]) && (j - i <= 2 || dp[i + 1][j - 1]);
                if(dp[i][j] && max_length < j - i + 1)
                {
                    max_length = j - i + 1;
                    answer = s.substr(i, max_length);
                }
            }
        }
        return answer;
    }
};

中心展开法:

class Solution {
public:
    string longestPalindrome(string s) {
        int length = s.length();
        if(length == 0)
            return "";
        int max_length = 0;
        string answer;
        for(int i = 0; i < length; ++i)
        {
            // odd case
            int offset = 0;
            while(i - offset >= 0 && i + offset < length && s[i - offset] == s[i + offset])
                offset++;
            if(max_length < 2 * offset - 1)
            {
                max_length = max(max_length, 2 * offset - 1);
                answer = s.substr(i - offset + 1, max_length);
            }
            
            // even case
            offset = 0;
            int j = i + 1;
            while(i - offset >= 0 && j + offset < length && s[i - offset] == s[j + offset])
                offset++;
            if(max_length < 2 * offset)
            {
                max_length = max(max_length, 2 * offset);
                answer = s.substr(i - offset + 1, max_length);
            }
        }
        return answer;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值