首页 > 其他分享 >【LeetCode Hot 100】5. 最长回文子串

【LeetCode Hot 100】5. 最长回文子串

时间:2024-09-17 14:46:46浏览次数:10  
标签:子串 int len start Hot 100 LeetCode dp 回文

题目描述

考虑回文字符串的特点,从左往右和从右往左读都是一样的,就是说字符串成了“轴对称”。要求一字符串的最长回文子串,我们可以遍历每个字符,求以该字符为轴对称中心的最长对称子串(或者以该字符和下一个字符为中间两个字符的对称子串),在所有这样的子串中长度最长的那个就是我们要找的答案。从回文字符串的对称性来想——这是一种相对直接的想法。

// C++
class Solution {
public:
    pair<int, int> expand(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] = expand(s, i, i);
            auto [left2, right2] = expand(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);
    }
};

回过头来考虑,对于一个子串,如果它是一个回文字符串,那么去除首尾两个字符(当然前提是该子串的长度大于2)它仍然是一个回文子串,反过来说,对于一个回文子串,如果它前后的两个字符相同,那么把这两个新字符加上所形成的新子串也一定是个回文子串。从动态规划的角度去想,我们就找到了这个问题的状态转移方程。如果使用\(P(i,j)\)表示字符串s的子串\(s[i:j]\)是否是回文子串,则有:

  • \(P(i,j)=true\),\(s[i:j]\)是回文子串
  • \(P(i,j)=false\),不是

我们可以写出状态转移方程:\(P(i,j)=P(i+1,j-1) \land (S_i == S_j)\)。显然,这些情况的讨论都是基于子串长度大于2的前提之上,动态规划的边界条件是我们必须考虑的,子串长度为1时,子串一定是回文串,子串长度为2时,当且仅当两个字符相同时子串是个回文串。实际编程时,我们可以通过子串长度和子串起始位置来进行循环。

// C++
class Solution {
public:
    string longestPalindrome(string s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }

        // dp[i][j]表示子串[i...j]是否是回文串
        vector<vector<int>> dp(len, vector<int>(len));
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }

        int begin = 0, max_len = 1;
        for (int L = 2; L <= len; L++) {
            for (int i = 0; i < len; i++) {
                int j = i + L - 1;
                if (j >= len) {
                    break;
                }

                if (s[i] != s[j]) {
                    dp[i][j] = false;
                } else if (j - i < 3) {
                    dp[i][j] = true;
                } else {
                    dp[i][j] = dp[i + 1][j - 1];
                }

                if (dp[i][j] && L > max_len) {
                    max_len = L;
                    begin = i;
                }
            }
        }

        return s.substr(begin, max_len);
    }
};

官方题解中提到,从动态规划法的状态转移方程中可以看出,所有状态在状态转移时的可能性都是唯一的,就是说所有状态都是从某个边界状态扩展得到的,这种所谓边界状态就是子串长度为1或2的状态,从这个角度看,可以得到最开始描述的“中心扩展算法”。

标签:子串,int,len,start,Hot,100,LeetCode,dp,回文
From: https://www.cnblogs.com/louistang0524/p/18417159

相关文章

  • leetCode2:两数相加(链表)
    题目:给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字0之外,这两个数都不会以0开头。思路:遍历两个链表,逐位相加,还要加上进位结......
  • Leetcode 85. 最大矩形
    1.题目基本信息1.1.题目描述给定一个仅包含0和1、大小为rowsxcols的二维二进制矩阵,找出只包含1的最大矩形,并返回其面积。1.2.题目地址https://leetcode.cn/problems/maximal-rectangle/description2.解题方法2.1.解题思路动态规划+单调栈,可以参考Leetcode84.柱......
  • Leetcode 297. 二叉树的序列化与反序列化
    1.题目基本信息1.1.题目描述序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序......
  • Leetcode 952. 按公因数计算最大组件大小
    1.题目基本信息1.1.题目描述给定一个由不同正整数的组成的非空数组nums,考虑下面的图:有nums.length个节点,按从nums[0]到nums[nums.length-1]标记;只有当nums[i]和nums[j]共用一个大于1的公因数时,nums[i]和nums[j]之间才有一条边。返回图中最大连通组件的大小......
  • Leetcode 19.删除链表的倒数第第N个结点
    1.题目基本信息题目:给你一个链表,删除链表的倒数第n个结点,并且返回链表的头结点。地址:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/2.解题方法2.1.解题思路使用快慢指针2.2.解题步骤第一步,初始化快指针为head,慢指针指向一个哑结点,哑结点......
  • Leetcode 2183. 统计可以被 K 整除的下标对数目
    1.题目基本信息1.1.题目描述给你一个下标从0开始、长度为n的整数数组nums和一个整数k,返回满足下述条件的下标对(i,j)的数目:0<=i<j<=n-1且nums[i]*nums[j]能被k整除。1.2.题目地址https://leetcode.cn/problems/count-array-pairs-divisible-by-k......
  • Leetcode—815. 公交路线【困难】(unordered_map+queue)
    2024每日刷题(163)Leetcode—815.公交路线bfs实现代码classSolution{public:intnumBusesToDestination(vector<vector<int>>&routes,intsource,inttarget){if(source==target){return0;}unordered_map<......
  • AnomalyLLM: Few-shot Anomaly Edge Detection for Dynamic Graphs using Large Langu
    本文是LLM系列文章,针对《AnomalyLLM:Few-shotAnomalyEdgeDetectionforDynamicGraphsusingLargeLanguageModels》的翻译。AnomalyLLM:使用大型语言模型对动态图进行少量异常边缘检测摘要1引言2相关工作3前言4方法5实验6结论摘要检测动态图的......
  • Java LeetCode每日一题
            1184.公交站间的距离    需求:        环形公交路线上有n个站,按次序从0到n-1进行编号。我们已知每一对相邻公交站之间的距离,distance[i]表示编号为i的车站和编号为(i+1)%n的车站之间的距离。        环线上的公交......
  • Day17 二叉树part07| LeetCode 235. 二叉搜索树的最近公共祖先 ,701.二叉搜索树中的插
    235.二叉搜索树的最近公共祖先235.二叉搜索树的最近公共祖先利用二叉搜索树的特性——有序树,可知,如果中间节点是p和q的公共节点,那个中间节点的数值一定在[p,q]区间因此,从根节点往下搜索,遇到的第一个位于[p,q]或[q,p]区间的节点就是最近公共祖先classSolution{......