【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]

你可能感兴趣的:(leetcode)