最长回文字符串

求最长回文字符串是面试中的一道经典题目!给定一个字符串s,从中找出最长的回文字符串:

比如:

s = “fggfsrtrsa”

返回 “srtrs”

解题思路:

其实最简单的可以用动态规划,时间复杂度为O(n^2),这种解法就不加赘述了。我这里会介绍时间复杂度为O(n)的算法:

Manacher算法:

首先用特定字符,比如"#",去填充原来的字符串s:
s = “#f#g#g#f#s#r#t#r#s#a#”
这样做的一个好处是:无论原字符串长度是奇是偶,都能变成奇数长度2*len(s)+1:

用Len数组去储存s中以每个位置为中心所能形成的最长回文字符串的边长:

显而易见,最长回文字串的长度就是max(Len)-1!最长回文字串的中点就在max(Len)所在位置!

从这里就能看出添加“#”的另一个好处:

无论什么情况,一个回文字串都可以以“从中心点发散”的形式表示,这样就能对应到s中的每个点!

不添加“#”,在遇到偶数回文串的时候就没法从中心点发散,比如 。

最后只需要从中心点截取前后max(Len)-1长度,再去掉“#”:
上述的例子,最后截取出来为 。

具体代码(Python3):

    def longestPalindrome(self, s):
        '''
        :param s: str
        :return: str
        '''
        s = list(s) #将str变为list
        Len = []
        length = len(s)
        for i in range(0, 2*length+1, 2): #在偶数位插入符号
            s.insert(i,'#')
        for i in range(len(s)):
            n = 1
            try:
                while s[i-n] == s[i+n]:
                    n += 1
            except IndexError:
                pass
            Len.append(n)
        max_len = max(Len)
        location = Len.index(max_len) #最长的Len在s列表中的位置
        palindrome = s[location - max_len + 1: location + max_len - 1]
        while '#' in palindrome:
            palindrome.remove('#')
        return ''.join(palindrome) #list变为str

你可能感兴趣的:(剑指offer)