# -*- coding: utf-8 -*-
'''
Python程序员面试算法宝典---解题总结: 第5章 字符串 5.10 如何求字符串里的最长回文子串
题目:
回文字符串是指一个字符串从左到右与从右到左遍历得到的序列是相同的。
例如"abcba"就是回文字符串,而"abcab"则不是回文字符串。
分析:
举例:
'cdefedfghi'的最长回文串是'defed'
'abcdefedcgh'的最长回文串是'cdefedc'
可以采取从中间向两边扩散的方式,扩散的标准是什么?
假设从字符串中间开始,以"cdefedfghiih"为例,
该字符串长度为12,中间的长度12/2=6,即对应
c d e f e d f g h i i h
从f开始
先对左边分析:
关键:
1 书上解法
对于字符串中每个字符Ci,根据字符串长度奇偶性
1) 以Ci为中心向两边扩展
2) 以Ci和Ci+1为中心向两边扩展
另外i的取值要为0~len(string)-1
因为需要遍历每个字符,对每个字符扩展
2 我想到没做出的原因是
1) 没有想到扩展函数的i,j可以是一样的,
这样可以用于求以某个字符为中心向两边扩展
2) 扩展字符的选取不应该是字符串的中心,而是每个字符都应该选取
所以时间复杂度为O(N*N)
参考:
Python程序员面试算法宝典
'''
class LongestPalindrome(object):
def __init__(self):
self.maxValue = 0
self.maxBegin = 0
# 判断以c1,c2为中心向两边扩散,返回回文串起始位置begin, 回文串长度size
def spread(self, string, i, j):
size = len(string)
while i >= 0 and j < size and string[i] == string[j]:
i -= 1
j += 1
length = j - i - 1
begin = i + 1
if length > self.maxValue:
self.maxValue = length
self.maxBegin = begin
def findLongestPalindrome(self, string):
if not string:
return string
size = len(string)
for i in range(0, size - 1):
# 以第i个字符向两边扩散
self.spread(string, i, i)
# 以第i和第i+1个字符向两边扩散
self.spread(string, i, i + 1)
result = string[self.maxBegin:self.maxBegin + self.maxValue]
return result
def reset(self):
self.maxValue = 0
self.maxBegin = 0
def process():
longestPalindrome = LongestPalindrome()
string = "cdefedfghiih"
result = longestPalindrome.findLongestPalindrome(string)
print result
longestPalindrome.reset()
string = "abcdefedcgh"
result = longestPalindrome.findLongestPalindrome(string)
print result
if __name__ == "__main__":
process()