首页 > 试题广场 >

最长回文子串

[编程题]最长回文子串
  • 热度指数:233868 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。


数据范围:
要求:空间复杂度 ,时间复杂度
进阶:  空间复杂度 ,时间复杂度
示例1

输入

"ababc"

输出

3

说明

最长的回文子串为"aba"与"bab",长度都为3
示例2

输入

"abbba"

输出

5
示例3

输入

"b"

输出

1
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        # write code here
        if A[::-1] == A:
            return len(A)
        if len(A) == len(set(A)):
            return 1
        for k in range(len(A)-1,0,-1):
            for i in range(len(A)-k):
                if A[i:i+k][::-1] == A[i:i+k]:
                    return k

发表于 2023-02-23 22:56:44 回复(0)
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        # write code here
        lst = []
        for i in range(len(A)):
            for j in range(i+1,len(A)):
                if A[i:j+1] == A[i:j+1][::-1]:
                    lst.append(len(A[i:j+1]))
        if not lst:
            return 1
        else:
            return max(lst)
发表于 2022-09-08 09:59:58 回复(0)
class Solution:
    def fun(self, s: str, begin: int, end: int) -> int:
        #每个中心点开始扩展
        while begin >= 0 and end < len(s) and s[begin] == s[end]: 
            begin -= 1
            end += 1
        #返回长度
        return end - begin - 1 
    def getLongestPalindrome(self , A: str) -> int:
        maxlen = 1
        #以每个点为中心
        for i in range(len(A) - 1): 
            #分奇数长度和偶数长度向两边扩展
            maxlen = max(maxlen, max(self.fun(A, i, i), self.fun(A, i, i + 1)))
        return maxlen

发表于 2022-08-22 10:40:17 回复(0)
from collections import deque


class Solution:
    def getLongestPalindrome(self, A) -> int:
        # write code here
        for i in range(len(A) - 1, 0, -1):
            for j in range(len(A) - i):
                if self.palcheck(A[j:j+i+1]):
                    return i+1
        return 1

    def palcheck(self, A: str):
        char_dequeue = deque()
        for ch in A:
            char_dequeue.append(ch)
        check = True
        while len(char_dequeue)>1 and check:
            first = char_dequeue.popleft()
            last = char_dequeue.pop()
            if first!=last:
                check = False
        return check


a = Solution().getLongestPalindrome(input())
print(a)
双队列的思路,不知道为啥提交不了
发表于 2022-07-31 17:30:24 回复(0)
class Solution:
    def getLongestPalindrome(self, A: str) -> int:
        # write code here
        dp = [1] * len(A)
        for i in range(1, len(A)):
            for j in range(i - 1, -1, -1):
                if A[j : i + 1] == A[j : i + 1][::-1]:
                    dp[i] = i - j + 1
        return max(dp)
发表于 2022-07-26 11:14:45 回复(0)

manacher算法
时间复杂度:O(n) 空间复杂度:O(n)
参考文献:Manacher算法的详细讲解

class Solution:
    def manacher(self, s, n, dp):
        ms = ''
        ms += '$#'
        for i in range(n):
            ms += s[i]
            ms += '#'
        index = 0
        maxpos = 0
        for i in range(len(ms)):
            if i < maxpos:
                dp[i] = min(dp[2*index-i], maxpos-i)
            else:
                dp[i] = 1
            while i - dp[i] > 0 and i + dp[i] < len(ms) and ms[i-dp[i]] == ms[i+dp[i]]:
                dp[i] += 1
            if i + dp[i] > maxpos:
                maxpos = i + dp[i]
                index = i

    def getLongestPalindrome(self , A: str) -> int:
        n = len(A)
        dp = [0 for i in range(n*2 + 2)]
        self.manacher(A, n, dp)
        res = 0
        for i in range(n*2+2):
            res = max(res, dp[i]-1)
        return res
发表于 2022-06-22 16:06:12 回复(0)
#动态规划
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        # write code here
        if not A:
            return 0
        dp = [[0 for i in range(len(A))] for j in range(len(A))]
        maxlen = 1
        for i in range(len(A)):
            for j in range(i,len(A)):
                if i == j:
                    dp[i][j] = 1
        for i in range(len(A)-2,-1,-1): # 这里左边指标用倒序是为了后面用到dp[i+1][j-1]时有值
            for j in range(1+i,len(A)):
                if A[i] == A[j]:
                    if j-i <= 2:
                        maxlen = max(maxlen, j-i+1)
                        dp[i][j] = 1
                    else:
                        dp[i][j] = dp[i+1][j-1]
                        if dp[i][j] == 1:
                            maxlen = max(maxlen, j-i+1)
        return maxlen

发表于 2022-05-31 15:33:19 回复(0)
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param A string字符串 
# @return int整型
#
class Solution:
    def fun(self, s, left, right):
        while left >=0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
        return right - left - 1
    # Manacher算法, 感觉有点想剪枝的策略
    def Manacher(self, s):
        S = '#'.join(list(s))
        S = '@#' + S + '#'
        P = [0 for _ in range(len(S)+10)]
        idx, mx, max_num, max_id= 0,0,0,0

        for i in range(1, len(S)):
            # 如果当前的i在最大回文半径内,则进行选择当前最大半径下标到当前下标的距离  和  对称位置2*idx - 1的最大半径 最小值
            # 然后进行从对应的半径P[i]进行开始向左和右进行搜索
            P[i] = min(P[2 * idx - i], mx - i) if mx > i else 1
            while i - P[i] >=0 and i + P[i] < len(S) and S[i + P[i]] == S[i - P[i]]:
                P[i] += 1
            # 如果当前的最大半径index大于当前的mx,则进行替换
            # 更新最大回文半径中心id
            if i + P[i] > mx:
                mx = i + P[i]
                idx = i
            if P[i] > max_num:
                max_num = P[i]
                max_id = idx
        return max_num - 1            
    def getLongestPalindrome(self , A: str) -> int:
        # write code here
        # 最长回文子串 O(n^2)
        # 从左到右进行遍历字符串,然后计算1、中心字符扩散;2、两个字符扩散
#         rel = 1
#         for i in range(len(A) - 1):
#             rel = max(rel, max(self.fun(A, i, i), self.fun(A, i, i+1)))
        return self.Manacher(A)

TIPS:对于O(n^2)的做法:
1、通过将字符串进行反转,然后使用动态规划计算和原始字符串的最长共同子串;
2、通过中心扩散的做法, 遍历一遍字符串,对于每个字符进行向两边扩散计算回文子串的最大长度;

对于时间复杂度O(n)的做法:
Manacher算法:
1、首先将字符串‘123456’,处理成‘@#1#2#3#4#5#6#’的形式;
2、然后设定一个备忘录dp[i],记录节点i的最大回文子串半径大小,设定额外两个变量idx,max_b,分别表示遍历过程中,当前字符前最大回文子串的中心下标以及最大回文子串的右界;
3、从头开始遍历,如果最大有界大于当前所遍历的字符下标,则取min(右界到当前下标的距离,当前下标在当下最大回文子串中心对称字符的最大半径P[2 *idx - cur_index]]),否则直接设定为1,
4、对当前字符可能的最大半径之后,进而从半径大小开始向两端遍历
5、如果更新后的当前字符的最大半径【右界】大于当前的右界,则进行更新右界和最大回文字符中心index
6、更新结果max_num【最终的max_num - 1则是最长回文子串的长度】

发表于 2022-05-08 20:39:47 回复(0)
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        dp = [[]]*len(A)
        dp[0] = [0]
        m = 1
        for i in range(1, len(A)):
            dp[i] = [i]
            for j in dp[i-1]:
                if j-1>=0 and A[j-1] == A[i]:
                    dp[i].append(j-1)
                    if i - j + 2 > m:
                        m = i - j + 2
                        print(i, j)
            if A[i] == A[i-1]:
                dp[i].append(i-1)
                if 2>m:
                    m=2
        return m
                

发表于 2022-04-04 21:28:17 回复(0)


#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#

# @param A string字符串 
# @return int整型
#
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        B = A[::-1]
        left=0
        res = ""
        for i in range(len(A)+1):
            if A[i-left:i] in B :
                res = A[i-left:i]
                left=left+1
        if res!=res[::-1]:
            
            res=res[1:]
            if res==res[::-1]:
                return len(res)
        return len(res)
        # write code here
        
        # write code here
发表于 2022-03-11 18:44:44 回复(0)
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        # f[i]: 以i为中心(奇数)或左中心(偶数)的最长回文长度
        # 膨胀法
        
        if len(A) == 1:
            return 1
        elif len(A) == 2:
            return 2 if A[0]==A[1] else 1
        
        f = [1 for _ in range(len(A))]
        
        for i in range(1, len(A)-1):
            # odd
            # 开始膨胀
            lpc = i-1
            rpc = i+1
            lengthOdd = 1
            while True:
                if lpc<0&nbs***bsp;rpc>=len(A)&nbs***bsp;A[lpc]!=A[rpc]:
                    break
                else:
                    lengthOdd += 2
                    lpc -= 1
                    rpc += 1
            # even
            lpc = i
            rpc = i+1
            lengthEven = 0
            # 开始膨胀
            while True:
                if lpc<0&nbs***bsp;rpc>=len(A)&nbs***bsp;A[lpc]!=A[rpc]:
                    break
                else:
                    lengthEven += 2
                    lpc -= 1
                    rpc += 1
            f[i] = max(lengthOdd, lengthEven)
        return max(f)

发表于 2022-03-04 00:18:22 回复(0)
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        # write code here
        a=[]
        if A==A[::-1]:
            return len(A)
        for i in range(len(A)):
            for j in range(i+1,len(A)):
                if A[i:j]==A[i-len(A):j-len(A)][::-1]:
                    a.append(j-i)
                if i==0 and A[:j]==A[:j-len(A)][::-1]:
                    a.append(j-i)
                
        return max(a)
                    
发表于 2022-03-01 09:19:40 回复(0)
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        arr = []
        for i in range(len(A)):
            for j in range(i,len(A)):
                if A[i] == A[j] and A[i+1:j] == A[i+1:j][::-1]:
                    arr.append(j-i+1)
        return max(arr)

发表于 2022-01-25 20:55:06 回复(0)
class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        # write code here
        n=len(A)
        dp=[[False]*n for _ in range(n)]
        max_len=1
        for i in range(n):
            dp[i][i]=True
        for L in range(2,n+1):
            for i in range(n):
                j=L+i-1
                if j>=n:
                    break
                if A[i]!=A[j]:
                    dp[i][j]=False
                else:
                    if L<=3:
                        dp[i][j]=True
                    else:
                        dp[i][j]=dp[i+1][j-1]
                if dp[i][j]==True and L>max_len:
                    max_len=L
        return max_len
       

发表于 2022-01-19 03:08:47 回复(0)
朋友们,我想问一下你们'ccbcabaabba'测出来的答案是多少呢?我最后的结果是6,最后数出来好像也是6?但是答案是4,是我理解的有问题还是这个case的答案有问题?
发表于 2021-12-11 17:54:45 回复(0)
class Solution:
    def getLongestPalindrome(self , A: str, n: int) -> int:
        # write code here
        A = list(A)
        results = []
        for idx, item in enumerate(A):
            
            # 检测 奇数个
            tmp = [item]
            for i in range(1, 1+min(idx, len(A)-idx-1)):
                if A[idx-i] == A[idx+i]:
                    tmp = [A[idx-i]] + tmp + [A[idx+i]]
                else:
                    break
            if len(tmp) >= len(results):
                results = tmp
            
            # 检测 偶数个
            tmp = []
            for i in range(1, 1+min(idx+1, len(A)-idx-1)):
                if A[idx-i+1] == A[idx+i]:
                    tmp = [A[idx-i+1]] + tmp + [A[idx+i]]
                else:
                    break
            if len(tmp) >= len(results):
                results = tmp
            
        return len(results)

发表于 2021-11-14 10:32:35 回复(0)