【回文串1 && 动态规划 && 马拉车算法】LeetCode 5. Longest Palindromic Substring

本文总结了LeetCode中15道与回文串相关的题目,详细介绍了两种高效求解最长回文子串的方法:动态规划法与马拉车算法。动态规划法通过维护一个二维数组记录字符串区间的回文特性,实现O(n^2)的时间复杂度;马拉车算法则巧妙地利用预处理技巧,将时间复杂度降低至O(n)。

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

LeetCode 5. Longest Palindromic Substring

LeetCode中与回文串相关的免费的题目共有15道(5, 9, 125, 131, 132, 214, 234, 336, 409, 479, 516, 564, 647, 680, 730),在此会整理成一个系列。
本博客转载自:http://www.cnblogs.com/grandyang/p/4464476.html
Solution1:动态规划
此题可以用动态规划Dynamic Programming来解,跟【132】Palindrome Partitioning II 拆分回文串之二的解法很类似,我们维护一个二维数组dp,其中dp[i][j]表示字符串区间[i, j]是否为回文串,当i = j时,只有一个字符,肯定是回文串,如果i = j + 1,说明是相邻字符,此时需要判断s[i]是否等于s[j],如果i和j不相邻,即i - j >= 2时,除了判断s[i]和s[j]相等之外,dp[j + 1][i - 1]若为真,就是回文串,通过以上分析,可以写出递推式如下:

dp[i, j] = 1                                 if i == j
         = s[i] == s[j]                      if i = j + 1
         = s[i] == s[j] && dp[i + 1][j - 1]  if i > j + 1     

答案代码:时间复杂度是 O(n2) O ( n 2 )

class Solution {
public:
    string longestPalindrome(string s) {
        int dp[s.size()][s.size()] = {0}, left = 0, right = 0, len = 0;
        for (int i = 0; i < s.size(); ++i) {//i,j组成一个形如左下三角矩阵
            for (int j = 0; j < i; ++j) {
                dp[j][i] = (s[i] == s[j] && (i - j < 2 || dp[j + 1][i - 1]));
                if (dp[j][i] && len < i - j + 1) {//把最大的回文子串长度存到len中
                    len = i - j + 1;
                    left = j;
                    right = i;
                }
            }
            dp[i][i] = 1;
        }
        return s.substr(left, right - left + 1);//substr()中首个参数是位置,第二个参数是字符个数
    }
};

Solution2:马拉车算法
马拉车算法介绍链接:
[1]https://blog.youkuaiyun.com/dyx404514/article/details/42061017能看懂,适合入门!
[2]http://www.cnblogs.com/grandyang/p/4475985.html在看懂[1]的基础上看[2]
此算法把时间复杂度降到了 O(n) O ( n ) !!!
向马拉车低头。。。

class Solution {
public:
    string longestPalindrome(string s) {
        string t ="$#";
        for (int i = 0; i < s.size(); ++i) {
            t += s[i];
            t += '#';
        }
        int p[t.size()] = {0}, id = 0, mx = 0, resId = 0, resMx = 0;
        for (int i = 0; i < t.size(); ++i) {
            p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;//核心代码
            while (t[i + p[i]] == t[i - p[i]]) ++p[i];//在现有基础上继续匹配
            if (mx < i + p[i]) {
                mx = i + p[i];
                id = i;
            }
            if (resMx < p[i]) {
                resMx = p[i];
                resId = i;
            }
        }
        return s.substr((resId - resMx) / 2, resMx - 1);
    }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值