【leetcode笔记】Python实现 5. Longest Palindromic Substring

5. Longest Palindromic Substring

Medium

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.

Example 2:

Input: “cbbd”
Output: “bb”

法1.暴力算法

第一步,通过两层for循环得到输入字符串s的所有可能子串。

第二步,逐个判断子串是否为回文串。若当前子串为回文串且长度大于之前得到的回文串,更新当前最长回文串。

代码

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # 法1.暴力算法 O(n^3) O(n) 超出时限
        lens = len(s)
        if lens < 2:
            return s
        maxlen = 0
        start = 0
        for i in range(lens):
            for j in range(i + 1, lens):
                begin = i
                end = j
                while begin <= end:
                    if s[begin] != s[end]:
                        break
                    else:
                        begin += 1
                        end -= 1
                if begin >= end and j - i +1 > maxlen:
                    maxlen = j - i + 1
                    start = i
        if maxlen > 0:
            return s[start:maxlen+start]
        return s[0]

法2.遍历字符串,中间扩展找

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # 法 2.遍历字符串 O(n^2) 
        res = ""
        for i in range(len(s)):
            # 奇数情况下:例如“aba”
            tmp = self.helper(s, i, i)
            if len(tmp) > len(res):
                res = tmp
                
            # 偶数情况下:例如“abba”
            tmp = self.helper(s, i, i+1)
            if len(tmp) > len(res):
                res = tmp
        return res
    
    def helper(self, s, l, r):
        while l >= 0 and r < len(s) and s[l] == s[r]:
            l -= 1
            r += 1
        return s[l+1: r]

法3.动态规划

动态规划,如果我们已经知道“abba”是一个回文,那么在它两边各加一个c,变成“cabbac”,那么得到的一定也是一个回文。根据这个性质,我们可以将问题规模缩小。维护一个二维的布尔型数组dp,dp[i][j]表示区间[i,j]的字符串是否为回文。可以知道dp的计算公式:
dp[i][j]=True               if (i == j)
dp[i][j]=(s[i]==s[j])           if (j - i == 1)
dp[i][j]=(s[i]==s[j]) && dp[i+1][j−1]  if (j - i >= 2)
可以合并为:
在这里插入图片描述

代码

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """        
        # 法3.动态规划 O(n^2) O(n^2)
        n = len(s)
        maxlen = 1
        if n < 2:
            return s
        start = 0
        dp = [[False for _ in range(n)] for i in range(n)]
        for j in range(n):
            for i in range(j):
                dp[i][j] = (s[i] == s[j]) and (j - i < 2 or dp[i+1][j-1])
                if dp[i][j] and (maxlen < j - i + 1):
                    maxlen = j -  i + 1
                    start = i
            dp[j][j] = True
        return s[start: start+maxlen]

4.manacher算法

#http://en.wikipedia.org/wiki/Longest_palindromic_substring

代码

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """        
        # 法4.manacher算法 O(n) and O(n)
        # Transform S into T.
        # For example, S = "abba", T = "^#a#b#b#a#$".
        # ^ and $ signs are sentinels appended to each end to avoid bounds checking
        T = '#'.join('^{}$'.format(s))
        n = len(T)
        P = [0] * n
        C = R = 0
        for i in range (1, n-1):
            P[i] = (R > i) and min(R - i, P[2*C - i]) # equals to i' = C - (i-C)
            # Attempt to expand palindrome centered at i
            while T[i + 1 + P[i]] == T[i - 1 - P[i]]:
                P[i] += 1
    
            # If palindrome centered at i expand past R,
            # adjust center based on expanded palindrome.
            if i + P[i] > R:
                C, R = i, i + P[i]
    
        # Find the maximum element in P.
        maxLen, centerIndex = max((n, i) for i, n in enumerate(P))
        return s[(centerIndex  - maxLen)//2: (centerIndex  + maxLen)//2]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值