python解决最长回文子串问题

来源:互联网 发布:php 手机号地区 编辑:程序博客网 时间:2024/06/07 03:35

今天在刷题的时候, 遇到了这道最长回文子串问题

Input: "babad"Output: "bab"Note: "aba" is also a valid answer.
(1)第一次暴力解决,结果直接超时

 def longestPalindrome(self, s):        self.start = 0        self.end = len(s) - 1        self.length = 0        self.result(s, self.start, self.end)        return s[self.start: self.end + 1]    def isPalindromic(self, s):        return s == s[-1::-1]        def result(self, s, start, end):        if (end - start + 1) > self.length:            if self.isPalindromic(s[start:end + 1]):                if (end - start + 1) > self.length:                    self.length = end - start + 1                    self.start, self.end = start, end                    return             if start < end:                self.result(s, start + 1, end)                self.result(s, start, end - 1)
看到超时的时候,来看看自己的代码,我感觉我的电脑没炸就好,如果给定的字符串非常的长,并且回文串很短 ,这样的话很容易造成栈溢出, 运行一个未通过的测试案例, 结果程序就没有动作了, 相对较短的字符串,这种暴力的解决方法是可以的.

(2)想到最长公共子串.

开始的暴力方法让自己超时, 因为回文串是对称的, 所以可以去考虑  正向的字符串和反向的字符串的最长公共子串, 想法很好,自己给的测试用例也过了, 但是还是不对 abcdasdfghdcba,这样会得到abcd /(ㄒoㄒ)/~~,根本就不是回文串啊.....

    代码想法很简单, 用一个二维数组记录最大的长度,这样可以得到最长公共子串.

                 a   b   b   d

             d  0   0   0   1

             b  0   1   1   0

             b  0   1   2   0

             a  1   0   0   0

       这是得到的二维矩阵, 但是上面的用例,我们是无法得到正确的结果. pass

     (3)查看资料找到了manacher算法 

    这个算法是以每一个字符为中心, 向两边发散,同时,用一个数组p来记录以每一个字符为中心的回文串的一半的长度.

     先看一下该算法的核心.

     确定以第i个字符为中心的回文串长度,建立在p[1:i-1]这个数组基础上

     假设, mx为当前字符串中已经确定的回文串的最有端. po为以mx为右端的回文串的中心,

     这时候,我们需要确定 第i个字符的位置是 > ma 还是 i <= mx

     如果 i <= mx 就是当前要确定的字符包含在前面的某个回文串里面, 回文串是对称的, 所以找到i 相对于po的对称位置 j, 

     接下来, 我们要做的就是判断, ①p[j] >= mx - i  or ②p[j] < mx - i

      在第一种情况, 就是说以i为中心的回文串还有向 mx右边伸展的可能, 然而那一部分还是未知数, 就的一步一步的去求解, 第二种情况, 就是 p[j] <= mx - i, 根据回文串的堆成性质, 可以确定

     p[i] = p[j]

     当i > mx的时候也是需要我们去一步一步的求解

     我在实现的时候只是给出最长回文串的一个, 

def commonSubstring(self, s1):        s1 = '#'+'#'.join(s1)+'#'        length = len(s1)        p = [0] * length        i = 0        id, mx = 0, 0        while i < length:            if mx > i:                p[i] = min(mx - i, p[2 * id - i])            else:                p[i] = 1            while (i - p[i] >= 0) and (i + p[i] < length) and (s1[i - p[i]] == s1[i + p[i]]):                p[i] += 1            if (i - 1 + p[i]) > mx:                mx = i -1 + p[i]                id = i            i += 1        max_length = max(p)        index_id = p.index(max_length)        s = s1[index_id + 1 - max_length:index_id + max_length]        s2 = ''        for i in s.split('#'):            s2 += i        return s2
     这个是我的实现, 终于明白了这个神奇的算法



原创粉丝点击