每天一道LeetCode-----最长回文子串/序列,从头开始的最长回文子串长度

博客介绍了如何解决LeetCode中的回文子串和子序列问题,包括Longest Palindromic Substring、Palindromic Substrings、Longest Palindromic Subsequence和Shortest Palindrome。文章通过动态规划和KMP算法详细解释了求解过程,特别是针对回文子串中心的处理和回文子序列的动态规划状态转移方程。
摘要由CSDN通过智能技术生成

Longest Palindromic Substring

原题链接 Longest Palindromic Substring
这里写图片描述
意思是找到最长的回文子串,注意子串和子序列的区别


蛮力法就将每个可能的子串都找出来判断是否是回文子串,找最大的那一个,速度上慢的吓人,光找子串的速度就到O(n2)了,所以此处需要找到一个简单的方法找到回文子串。
既然回文子串是从中心开始向两边延伸时,左右两边相同,那么就可以从每个字符开始都向两边延伸,看能找到的最长回文子串是多长就行了。

这就出现了一个问题,回文子串的中心是什么地方,对于abcba来说,中心是c。那么对于abccba呢,中心是cc中间的位置,这个位置没有明确的下标。二者的区别在于一个数量上一个是奇数,一个是偶数。为了统一,这里有一种技巧,就是将源字符串s统一转化成奇数个数,方法是虚拟的加上一些字符,注意是虚拟加,实际上并不改变源s,假设s为babad,那么加上虚拟字符的s是#b#a#b#a#d#,这样,不管什么字符串全都是奇数个数了,总数为2 * s.size() + 1,而这里还有一个巧妙的地方,就是加上虚拟字符后的字符的索引除以2正好是在源s中没有加上虚拟字符的索引,这里把加上虚拟字符后的s成为extend_s

#   b   #   a   #   b   #   a   #   d   #   extend_s
0   1   2   3   4   5   6   7   8   9   10  extend_s的下标索引
0   0   1   1   2   2   3   3   4   4   5   除以2后的结果

b   a   b   a   d   s
0   1   2   3   4   s的下标索引

所以在程序中遍历extend_s时只需要除以2,就可得得到s中对应位置的字符。

扩展s是为了解决奇数偶数的问题,这个问题存在在什么地方呢。比方说要找的结果是abccba,那么在切割的时候是从cc中间切分的,而对于abcba而言,切分是在c字符上切分的,这个还好说,切分的位置有正常的索引下标,可是abccba的切分位置是中间,下标是x.5?,不存在的。所以扩展后的s刚好解决的就是这个难题

a   b   c   c   b   a   源字符串s
0   1   2   3   4   5   下标索引
          |
       切分位置

#   a   #   b   #   c   #   c   #   b   #   a   #   扩展字符串extend_s
0   1   2   3   4   5   6   7   8   9   10  11  12  下标索引
                        |
                     切分位置
-----------------------------------------------------------------

a   b   c   b   a   源字符串s
0   1   2   3   4   下标索引
        |
     切分位置

#   a   #   b   #   c   #   b   #   a   #   扩展字符串extend_s
0   1   2   3   4   5   6   7   8   9   10  下标索引
                    |
                 切分位置

通过扩展,不管是奇数个数的字符串还是偶数个数的字符串,都有一个明确的下标表示切分位置,这个位置正是回文子串的中心。程序就简单多了,从extend_s的每一个字符开始,向两边扩展,相等则继续扩展,不相等则停止扩展。需要注意的是,程序中遍历的仍然是源字符串s,只是在下标上做了点手脚,所以区分#还是字母的方法就看下标是奇数还是偶数,#的下标永远是偶数。代码如下

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.size() <= 1)
            return s;

        string ans("");
        for(int i = 0; i < 2 * s.size() + 1; ++i)
        {   
            
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值