您的位置:首页 > 其它

【Leetcode】214. Shortest Palindrome 最短回文串

2019-01-28 17:37 417 查看

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.

Example 1:

Input: “aacecaaa”
Output: “aaacecaaa”

Example 2:

Input: “abcd”
Output: “dcbabcd”

解法

这题的重点其实是要找到以

s[0]
开头的最长回文子串的长度

解法一:马拉车

详细解释在516. Longest Palindromic Subsequence
我自己是用这个算法解的,这个算法本来是用来遍历一遍所有可能的中点,然后对每个中点计算最长回文子串的,我们只需要遍历一半的中点,中点越靠右半径越大

class Solution(object):
def shortestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
n = len(s)
l = 2*n-1
p = [0]*l
rm = 0
ans = 1

def equal(i,r):
if (i+r)%2!=0:
return True
return s[(i+r)//2]==s[(i-r)//2]

for i in xrange(1,n):
if i<=rm+p[rm]:
p[i] = min(rm+p[rm]-i,p[2*rm-i])
while i-p[i]>0 and i+p[i]<l-1 and equal(i,p[i]+1):
p[i] += 1
if i+p[i]>rm+p[rm]:
rm = i
if i-p[i]==0:
ans = (i+p[i])//2+1
return s[ans:][::-1]+s

解法二:KMP

KMP的核心是

next[i]=j
表示
s[0..j-1]=s[i-j..i-1]

一开始我也想用KMP,但是只在原字符串用KMP有个问题,就是i不可能等于j,所以不会遍历到回文子串。
我们可以新建一个大的字符串:
ss=s+"#"+s[::-1]
,它的长度为
2*n+1
"#"
的下标为
n

这样,对于
ss[0..j-1]=ss[i-j,i-1]
。由于中间被
#
隔开了,所以一定有
j-1<n
i-j>n
。那么,当
i=2n+1
(也就是
ss[i-1]
对应
s[0]
)时,
next[i]
就是以
s[0]
开头的最长回文子串的长度

class Solution(object):
def shortestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
n = len(s)
ss = s+'#'+s[::-1]
f = [-1]*(2*n+2)
for i in xrange(1,2*n+2):
j = f[i-1]
while j>=0 and ss[j]!=ss[i-1]:
j = f[j]
f[i] = j+1 if j>=0 else 0
return s[f[i]:][::-1]+s
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: