【LeetCode 中等题】3-最长回文子串

声明:

今天是中等题第3道题。给定一个字符串 s,找到 s 中最长的回文子串。以下所有代码经过楼主验证都能在LeetCode上执行成功,代码也是借鉴别人的,在文末会附上参考的博客链接,如果侵犯了博主的相关权益,请联系我删除

(手动比心ღ( ´・ᴗ・` ))

正文

题目:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"
输出: "bb"

解法1。从头开始遍历每个元素看看是不是回文串中心,对于每个元素,它有可能是回文串的中心(奇数个字符),也有可能和它的下一个字符构成回文串的中心(偶数个字符),由此判断长度是不是更长来决定是否要更新起始index,代码如下。

执行用时: 932 ms, 在Longest Palindromic Substring的Python3提交中击败了66.74% 的用户

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s:
            return
        len_s = len(s)
        for i in range(len_s):
            len1 = self.helper(s,i,i,len_s)    # 本身是回文串中心的情况
            len2 = self.helper(s,i,i+1,len_s)  # 本身+下一个元素是回文串中心的情况
            len_m = max(len1,len2)
            if len_m > end-start+1:    # 如果新的最长回文串长度大于原来的就更新原回文串始末index
                start = i - (len_m-1)//2
                end = i + len_m//2
        return s[start:end+1]


    # 该函数用于计算从当前元素左右扩展直到不是回文串为止的index
    def helper(self,s,L,R,len_s):
        while L >= 0 and R < len_s and s[L] == s[R]:
            L -= 1
            R += 1
        return R - L - 1

                

解法2。还有种算法Manacher,但我没看太懂,而且下面的代码求的是最长回文串长度,姑且看看,也许以后就懂了

def manacher(s):
    #预处理
    s='#'+'#'.join(s)+'#'

    RL=[0]*len(s)
    MaxRight=0
    pos=0
    MaxLen=0
    for i in range(len(s)):
        if i<MaxRight:
            RL[i]=min(RL[2*pos-i], MaxRight-i)
        else:
            RL[i]=1
        #尝试扩展,注意处理边界
        while i-RL[i]>=0 and i+RL[i]<len(s) and s[i-RL[i]]==s[i+RL[i]]:
            RL[i]+=1
        #更新MaxRight,pos
        if RL[i]+i-1>MaxRight:
            MaxRight=RL[i]+i-1
            pos=i
        #更新最长回文串的长度
        MaxLen=max(MaxLen, RL[i])
    return MaxLen-1



# V 2.0
# manacher算法
def manacher(self):
        s = '#' + '#'.join(self.string) + '#'               # 字符串处理,用特殊字符隔离字符串,方便处理偶数子串
        lens = len(s)
        f = []                                          # 辅助列表:f[i]表示i作中心的最长回文子串的长度
        maxj = 0                                        # 记录对i右边影响最大的字符位置j
        maxl = 0                                        # 记录j影响范围的右边界
        maxd = 0                                        # 记录最长的回文子串长度
        for i in range(lens):                           # 遍历字符串
            if maxl > i:
                count = min(maxl-i, int(f[2*maxj-i]/2)+1)  # 这里为了方便后续计算使用count,其表示当前字符到其影响范围的右边界的距离
            else :
                count = 1
            while i-count >= 0 and i+count < lens and s[i-count] == s[i+count]:  # 两边扩展
                count += 1
            if(i-1+count) > maxl:                         # 更新影响范围最大的字符j及其右边界
                maxl, maxj = i-1+count, i
            f.append(count*2-1)
            maxd = max(maxd, f[i])                       # 更新回文子串最长长度
        return int((maxd+1)/2)-1                        # 去除特殊字符

结尾

解法1:官方解法

解法2:https://segmentfault.com/a/1190000003914228   https://blog.csdn.net/asd136912/article/details/78987624

猜你喜欢

转载自blog.csdn.net/weixin_41011942/article/details/84545382