Shortest Palindrome

题目描述

Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.

For example:

Given "aacecaaa", return "aaacecaaa".

Given "abcd", return "dcbabcd".

解题方法

这一道题可以借鉴longest palindrome substring的方法,从每个pivot搜palindrome, 如果左边能够停留在开头,说明可以通过在开头加characters找到shortest palindrome.

注意

  • 这里其实只需要找一半, 因为结果的左半部分不完整,必然是在前半部分有一个pivot
  • 从后往前扫,这样找到了结果就可以返回了

KMP解法

O(n)的算法,需要理解一下 理解kmp kmp geeksfor geeks shortest Palindrome

Solution

利用longest palindrome substring

python超时

class Solution(object):
    def shortestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s:
            return ""

        length = len(s)
        minLength = sys.maxint
        result = ""
        if self.isPalindrome(s):
            return s


        if length % 2 == 1:
            half = length / 2 + 1
        else:
            half = length / 2

        for i in range(1, half):
            # pivot is between i-1, i
            low = i - 1
            high = i
            while low >= 0 and high < length and s[low] == s[high]:
                low -= 1
                high += 1
            if low == -1:
                pLength = (high - 1) - (low + 1) - 1
                doubleLength = (length - 1) - high + 1
                if minLength > pLength + 2 * doubleLength:
                    minLength = pLength + 2 * doubleLength
                    result = s[length-1:high-1:-1] + s

            # pivot is i
            low = i - 1
            high = i + 1
            while low >= 0 and high < length and s[low] == s[high]:
                low -= 1
                high += 1
            if low == -1:
                pLength = (high - 1) - (low + 1) - 1
                doubleLength = (length - 1) - high + 1
                if minLength > pLength + 2 * doubleLength:
                    minLength = pLength + 2 * doubleLength
                    result = s[length-1:high-1:-1] + s
        return result

    def isPalindrome(self, s):
        length = len(s)
        if length == 0 or length == 1:
            return True

        left, right = 0, length - 1
        while left < right:
            if s[left] == s[right]:
                left += 1
                right -= 1
            else:
                return False
        return True
class Solution(object):
    def shortestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s:
            return ""

        length = len(s)
        minLength = sys.maxint
        result = ""
        if self.isPalindrome(s):
            return s

        for i in range(length / 2, -1, -1):
            # pivot is between i-1, i
            if s[i] == s[i-1]:
                result = self.scanFromCenter(s, i-1, i)
                if result:
                    return result
            else:
                result = self.scanFromCenter(s, i, i)
                if result:
                    return result

    def scanFromCenter(self, s, l, r):
        while l >= 0 and r < len(s) and s[l] == s[r]:
            l -= 1
            r += 1

        if l >= 0:
            return None

        result = s[len(s)-1:r-1:-1] + s


    def isPalindrome(self, s):
        length = len(s)
        if length == 0 or length == 1:
            return True

        left, right = 0, length - 1
        while left < right:
            if s[left] == s[right]:
                left += 1
                right -= 1
            else:
                return False
        return True

Reference