214. 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.
解释:
给一个字符串,让我们生成最小的回文串,只能在字符串的前面插入新的字符串
思考:
先找到以第一个字符开头的回文串,然后把剩下的部分倒过来。所以问题转换为如何求以第一个字符开头的最长回文串。 这里介绍求解回文串类问题非常经典的马拉车算法,时间复杂度是On 首先,把字符串的所有间隔,使用#填充,这样就可以解决奇偶问题。(也可以不填充,不填充更加直观一些) 其次,定义两个变量,center和maxRight,分别代表当前maxRight对应的回文串的中心,以及当前所有回文串最右边界。 再次,定义一个数组P,用来记录每个位置对应的最长单边长度。 最后核心的来了,对于i大于center小于maxRight时,p[i] = min(maxRight - i, p[mirror]),mirror就是2center-i 道理就是以i为中心的回文串,对应的镜像位置一定也是回文串。i延伸的长度不可能比他镜像位置延伸的长,否则maxRight将会延伸。 对于i超出maxRight时只需要正常扩展即可。 具体到这个题,先统计所有的On,然后找到长度等于下标的最大下标返回即可。
答案:
class Solution(object):
def shortestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
nextS='#'+("#").join(list(s))+"#"
center=-1
maxRight=-1
p=[1]*len(nextS)
for i in range(len(nextS)):
if i >=maxRight:
j=0
while nextS[i+j]==nextS[i-j]:
j+=1
if i-j<0 or i+j>=len(nextS):
j-=1
break
maxRight=i+j-1
center=i
p[i]=1+j
else:
p[i]=min(maxRight-i,p[2*center-i])
res=0
for i in range(len(p)):
if i==p[i]-1:
res=max(res,i)
sC=s[res:]
return sC[::-1]+s