最长回文子串

来源:互联网 发布:python shell怎么打开 编辑:程序博客网 时间:2024/06/11 15:12

最长回文子串可以采用动态规划的思想进行计算,也可以进行变化,采用对称的原理进行。下面的代码注释中分别给出了基本思想和不同的解决方案,并给出了复杂度分析。



'''Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.'''class Solution3:    '''    brute force algorithm, check all possible substring.    O(n^3)    this is reallys bad.    '''    # @param {string} s    # @return {string}    def longestPalindrome(self, s):        if s == None: return None        max_len = 0        longestPalindrome = None        for i in range(len(s)):            for j in range(i, len(s)):                substr = s[i:j + 1]                if self.isPalindrome(substr):                    if len(substr) > max_len:                        max_len = len(substr)                        longestPalindrome = substr        return longestPalindrome    def isPalindrome(self, str):        i, j = 0, len(str) - 1        while i <= j:            if str[i] != str[j]:                return False            i += 1            j -= 1        return Trueclass Solution2s:    '''    O(2^n)    dynamic programming, recursive call.    This really bad. too much recursive call, and recompute the same sub problem multiply times.    '''    # @param {string} s    # @return {string}    def longestPalindrome(self, s):        if s == None: return None        if len(s) <= 1: return s        i, j = self.find(s, 0, len(s) - 1)        return s[i:j+1]    def find(self, s, i, j):        '''        recursive call to find palindrome        '''        # base case        if i == j: return i, j        elif i + 1 == j and s[i] == s[j]: return i, j        else:            if s[i] == s[j]:                r1, r2 = self.find(s, i+1, j-1)                if r1 == i+1 and r2 == j-1: return i, j            r1, r2 = self.find(s, i, j-1)            r3, r4 = self.find(s, i+1, j)            if r2 - r1 > r4 - r3: return r1, r2            else: return r3, r4class Solution2:    '''    O(n^2)    space: O(n^2)    dynamic programming, using back trace to compute palindrome.    This algorithm is not good enough.    '''    # @param {string} s    # @return {string}    def longestPalindrome(self, s):        if s == None: return None        if len(s) <= 1: return s        max_len = 0        longest = ''        table = [[0 for j in range(len(s))] for i in range(len(s))]        for i in range(len(s)):            table[i][i] = 1        for i in range(len(s) - 1):            if s[i] == s[i+1]: table[i][i+1] = 1        begin_len = 3        for length in range(begin_len, len(s) + 1):            for i in range(len(s) - length + 1):                j = i + length - 1                if s[i] == s[j] and table[i+1][j-1] == 1:                    table[i][j] = 1                    if length > max_len:                        max_len = length                        longest = s[i:j+1]        return longestclass Solution1:    '''    find palindrom for each char in the string. some trick for odd/even palindrome    O(n^2)    space: O(1)    could pass leetcode    '''    # @param {string} s    # @return {string}    def longestPalindrome(self, s):        if s == None: return None        if len(s) <= 1: return s        longest = ''        for i in range(len(s)):            temp = self.find(s, i, i)            if len(temp) > len(longest): longest = temp            temp = self.find(s, i, i + 1)            if len(temp) > len(longest): longest = temp        return longest    def find(self, s, left, right):        while left >= 0 and right <= len(s) - 1 and s[left] == s[right]:            left -= 1            right += 1        return s[left+1:right]class Solution:    '''    using symmetric information of already checked substring.    O(n)    space: O(n)    '''    # @param {string} s    # @return {string}    def longestPalindrome(self, s):        if s == None: return None        if len(s) <= 1: return s        longest, mid = 0, 0        s2 = '#'.join(s)        s2 = '#' + s2 + '#'        p = [1 for i in range(len(s2))] # radius of palindrome of each char        center, maxid = 0, 0        for i in range(len(s2)):            if maxid > i:                sym = 2 * center - i # find symmetric point                if sym >= 0: p[i] = min(p[sym], maxid - i)                else: p[i] = maxid - i            while i- p[i] >= 0 and i + p[i] < len(s2) and s2[i- p[i]] == s2[i + p[i]]:                p[i] += 1            if p[i] + i > maxid:                maxid = p[i] + i                center = i            if p[i] > longest:                 longest = p[i]                mid = i        # construct results string        res = []        for i in range(mid - longest + 1, mid + longest):            if s2[i] != '#': res.append(s2[i])        return ''.join(res)      if __name__ == '__main__':        #so = Solution()    so = Solution2s()    s1 = ''    s2 = 'a'    s3 = 'ab'    s4 = '123aba'    s5 = '123abcba23'    s6 = '123abccba23'    s7 = 'ccc'    s8 = 'accc'    s9 = 'abbbbbba'    s10 = "aaabaaaa"    s11 = 'tattarrattat'    s12 = 'abaaaa'    s13 = "bananas"    s = "civilwartestingwhetherthatnaptionoranynartionsoconceivedandsodedicatedcanlongendureWeareqmetonagreatbattlefiemldoftzhatwarWehavecometodedicpateaportionofthatfieldasafinalrestingplaceforthosewhoheregavetheirlivesthatthatnationmightliveItisaltogetherfangandproperthatweshoulddothisButinalargersensewecannotdedicatewecannotconsecratewecannothallowthisgroundThebravelmenlivinganddeadwhostruggledherehaveconsecrateditfaraboveourpoorponwertoaddordetractTgheworldadswfilllittlenotlenorlongrememberwhatwesayherebutitcanneverforgetwhattheydidhereItisforusthelivingrathertobededicatedheretotheulnfinishedworkwhichtheywhofoughtherehavethusfarsonoblyadvancedItisratherforustobeherededicatedtothegreattdafskremainingbeforeusthatfromthesehonoreddeadwetakeincreaseddevotiontothatcauseforwhichtheygavethelastpfullmeasureofdevotionthatweherehighlyresolvethatthesedeadshallnothavediedinvainthatthisnationunsderGodshallhaveanewbirthoffreedomandthatgovernmentofthepeoplebythepeopleforthepeopleshallnotperishfromtheearth"    print so.longestPalindrome(s1)    print so.longestPalindrome(s2)    print so.longestPalindrome(s3)    print so.longestPalindrome(s4)    print so.longestPalindrome(s5)    print so.longestPalindrome(s6)    print so.longestPalindrome(s7)    print so.longestPalindrome(s8)    print so.longestPalindrome(s9)    print so.longestPalindrome(s10)    print so.longestPalindrome(s11)    print so.longestPalindrome(s12)    print so.longestPalindrome(s13)


原创粉丝点击