leetcode 最长回文子串问题

今天刷leetcode时遇到的最长回文子串问题:

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
输入: "cbbd"
输出: "bb"

我用的是Manacher算法算法,时间复杂度O(n)),为什么代码在执行时反倒没有中心扩展算法(时间复杂度O(n^2))的快呢?

下面是我的代码:

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if len(s) == 1:
            return s
        # 预处理,添加字符'#'解决字符串长度分奇偶的问题
        ss = '#' + '#'.join(s) + '#'
        
        # 初始化
        pos = 0                           # 对称轴
        maxpos = 0                        # 最大位置
        maxright = 0                      # 最大右边界
        lenss = len(ss)                   # 字符串长度
        p = [0] * lenss                   # 对称半径列表
        
        # 主循环
        for i in range(lenss): 
            # 判断是否在右边界以内
            if i < maxright:
                # 设置p[i]的值
                p[i] = min(p[2*pos-i], maxright-i)
            else:
                p[i] = 1
            
            # 当没有到字符串首或尾时扩展边界
            while ((i - p[i]) > 0) and ((i + p[i]) < lenss) and (ss[i-p[i]] == ss[i+p[i]]):
                p[i] += 1
            
            # 更新边界
            if maxright < i + p[i] -1:
                maxright = i + p[i] -1
                pos = i
            
            # 更新最大索引
            if p[i] > p[maxpos]:
                maxpos = i
        
        return ss[maxpos-(p[maxpos]-1):maxpos+p[maxpos]].replace('#','')


喜欢这个问题 | 分享 | 新建回答

回答

东方不败

Nov 21, 2018
0 赞

其实不管是否是中心测试法,还是其他的测试法,都肯定是第二层循环。而核心拼速度的就是减枝(虽然这不是深度搜索,但是也是适用的)。用已经获得的最大的值去测试一下,如果行,继续扩大长度来实验;如果不行,那就说明这个点测试不出来更大的,那就不用继续去实验了。这样就可以很明智地撸一遍,撸得很轻松。

这应该属于动态规划的思路。



jerkzhang

Nov 21, 2018
0 赞

乍看一下,你这似乎有两层循环~ while也是循环吧,另外while这么来写,我感觉有点变扭,不过也许是我个人习惯吧(我会使用while true加break跳出来写,不过这是细节,很可能是我个人习惯,最终形成了我的阅读逻辑习惯,我感觉这样写逻辑上会更清楚;不过这个事情很细节,而且是一个有争议的细节。不用管)

不管哪种算法,如果是追求速度与效率;我感觉有相当多的情况下都是空间换速度。



BlackA

Nov 20, 2018
0 赞

是我的代码还可以优化还是Leetcode的测试样本有问题?

:)