1088 最长回文子串
回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。
输入一个字符串Str,输出Str里最长回文子串的长度。
Input
输入Str(Str的长度 <= 1000)
Output
输出最长回文子串的长度L。
Input示例
daabaac
Output示例
5
解题方法
该题解题方法有两种,一种是直接暴力,一种是运用Manacher算法解题。
暴力解法是,每次规定一定的长度,然后判断等于该长度的所有子串是否有符合回文的。先从最长的长度开始遍历判断,依次递减,直到遇到符合条件的就停止。
但是暴力解法不适合数据过大的情况,而Manacher算法可以。
Manacher算法的讲解可以看这一篇博客——求字符串的最长回文子串
还有一篇是用python设计最长回文子串代码——Python算法实践——最长回文串
解题代码
暴力解法
#判断[l, r]区间的子串是否为回文字符串
def check(s, l, r):
#m为反转字符串
if l == 0:
m = s[r::-1]
else:
m = s[r:l-1:-1]
return m == s[l:r+1]
while True:
try:
s = input()
ls = len(s)
End = ans = 0
#length为子串长度,l为子串左边界
for length in range(ls, 0, -1):
for l in range(ls-length+1):
r = l + length - 1
if check(s, l, r):
End = 1
ans = length
break
if End:
break
print(ans)
except EOFError:
break
暴力很好理解,但是时间复杂度高,此代码在51Nod上跑了一千多ms,而Manacher算法仅仅只需要近百ms。
Manacher算法解法
def Manacher(s):
#join是用于在s中插入#
s = '*#' + '#'.join(s) + '#'
ls = len(s)
p = []
#id为回文子串中心,mx为回文子串右边界,ans记录最长回文子串长度
id = mx = ans = 0
for i in range(ls):
#pi记录以id(也是i)为中心的最大回文子串长度
#首先利用对称性质找到以id为中心的最长回文子串长度
pi = min(p[2*id-i], mx - i) if mx > i else 1
#然后扩展两边去找回文子串
while i+pi < ls and i-pi >= 0 and s[i+pi] == s[i-pi]:
pi += 1
# mx记录回文子串能触摸到的最大有边界
if i+pi > mx:
mx = i+pi
id = i
ans = max(ans, pi)
p.append(pi)
return ans-1
while True:
try:
s = input()
print(Manacher(s))
except EOFError:
break