LeetCode 力扣 热题 100道(五)最长回文子串(C++)

最长回文子串

给你一个字符串 s,找到 s 中最长的 回文子串。

回文性

如果字符串向前和向后读都相同,则它满足 回文性

子字符串
子字符串 是字符串中连续的 非空 字符序列。

动态规划法

cpp 复制代码
class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        if (n <= 1) return s;

        vector<vector<bool>> dp(n, vector<bool>(n, false));
        int start = 0, maxLen = 1;

        for (int i = 0; i < n; ++i) dp[i][i] = true;
        for (int i = 0; i < n - 1; ++i) {
            if (s[i] == s[i + 1]) {
                dp[i][i + 1] = true;
                start = i;
                maxLen = 2;
            }
        }

        for (int len = 3; len <= n; ++len) {
            for (int i = 0; i + len - 1 < n; ++i) {
                int j = i + len - 1;
                if (s[i] == s[j] && dp[i + 1][j - 1]) {
                    dp[i][j] = true;
                    start = i;
                    maxLen = len;
                }
            }
        }

        return s.substr(start, maxLen);
    }
};

首先,我们获取字符串 s 的长度 n。如果字符串长度小于或等于 1,则字符串本身就是回文的(单个字符本身就是回文),直接返回字符串。

dp 是一个二维布尔型数组,dp[i][j] 用来表示子串 s[i...j] 是否为回文串。数组大小为 n x n,初始化为 false。

每个单字符子串(即 s[i...i])自然是回文的,因此将 dp[i][i] 设置为 true。

接下来,我们处理长度为 2 的子串。如果 s[i] == s[i+1],那么 s[i...i+1] 是回文串,设置 dp[i][i+1] = true。此时,我们还更新 start 和 maxLen,记录最长回文子串的起始位置和长度。

从长度为 3 的子串开始,我们逐步扩展到更长的回文子串。具体来说,len 表示当前子串的长度,从 3 一直增加到 n。

对于每个长度为 len 的子串,我们通过以下条件判断是否为回文:

  • s[i] == s[j]:当前子串的首尾字符相同。
  • dp[i+1][j-1]:即子串 s[i+1...j-1] 是否是回文。

如果这两个条件都成立,那么 s[i...j] 也是回文子串,更新 dp[i][j] = true,并更新 start 和 maxLen,记录当前最长回文子串的起始位置和长度。

输入字符串 s = "babad":

  • 长度为 1 的子串 :我们从一开始就知道每个单独的字符都是一个回文子串,所以 dp[i][i] = true 对于所有 i 都成立。对于 s = "babad",初始化时,dp 数组是这样的:

dp = [ [true, false, false, false, false], [false, true, false, false, false], [false, false, true, false, false], [false, false, false, true, false], [false, false, false, false, true] ]

  • 长度为 2 的子串 :接着,代码检查相邻的字符是否相同。如果相同,设置 dp[i][i+1] = true。在 s = "babad" 中,s[0] != s[1](b != a),s[1] != s[2](a != b),s[2] != s[3](b != a),s[3] != s[4](a != d)。所以 dp 数组没有更新。

dp 仍然是:

dp = [ [true, false, false, false, false], [false, true, false, false, false], [false, false, true, false, false], [false, false, false, true, false], [false, false, false, false, true] ]

  • 长度为 3 及以上的回文子串 :接着,程序检查长度为 3 及以上的子串,逐步扩展回文子串的长度。对每一个 len(长度从 3 到 n),我们依次检查每个子串的起始位置 i。

    • 当 len = 3 时:

      • 对于 s[0...2] = "bab",s[0] == s[2](b == b),并且 dp[1][1] = true(即 "a" 是回文)。所以 dp[0][2] = true,start = 0,maxLen = 3。
      • 现在 dp 数组更新为:

      dp = [ [true, false, true, false, false], [false, true, false, false, false], [false, false, true, false, false], [false, false, false, true, false], [false, false, false, false, true] ]

      这时,我们已经找到了 "bab" 作为一个回文子串。

  • 继续检查更长的回文子串:

    • 当 len = 4 时 :
      • 对于 s[1...4] = "abad",s[1] != s[4](a != d),所以 dp[1][4] 不会被设置。
    • 当 len = 5 时 :
      • 对于 s[0...4] = "babad",s[0] != s[4](b != d),所以 dp[0][4] 也不会被设置。

经过这些步骤,程序最终会返回最长的回文子串 "bab",因为 start = 0 和 maxLen = 3。

相关推荐
aqiu1111113 小时前
【C++算法打怪专栏】8. 字符串转换整数 (atoi)
开发语言·c++·算法
爱吃香菜的初学者4 小时前
十四.Linux——消息队列
linux·运维·开发语言
迅猛龙办公室4 小时前
python实现倒序输出数字
开发语言·python
h39748 小时前
DirectShow过滤器开发-视频源过滤器
c++·windows·音视频·directshow
夏幻灵10 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
程序猿编码10 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
西飘客11 小时前
vs 怎么根据dll 生成lib文件
c++·qt
bkspiderx11 小时前
Qt 插件机制:动态扩展应用功能的核心框架
开发语言·qt·元数据·qt 插件·qpluginloader
程序员老陆11 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
沐晓时光12 小时前
C语言入门,深入理解指针(3)
c语言·开发语言