题目:Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
链接:https://oj.leetcode.com/problems/longest-palindromic-substring/
描述:求最大长度的回文子串
解法:常见的解法有DP和中间向外扩展两种方式,时间复杂度O(n^2),而该复杂度算法使用python会出现TLE,采用时间复杂度为O(n)的Manacher算法可过python。
Manacher算法根据已发现的最长回文子串确定新子串的最大长度,算法介绍见:http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html
solution implemented by Manacher's algorithm in python:
class Solution:
# @return a string
def longestPalindrome(self, s):
s_pro = self.preProcess(s)
p = [0 for i in range(len(s_pro))]
c=0;r=0
for i in range(1, len(s_pro)-1):
_i = 2*c - i
p[i] = min(p[_i], r-i) if r>i else 0
while s_pro[i-p[i]-1] == s_pro[i+p[i]+1]: p[i] += 1
if p[i]+i > r:
c = i
r = p[i]+i
maxlen = 0; ct=0;
for i in range(len(s_pro)):
if p[i] > maxlen: maxlen=p[i];ct=i;
return s[(ct-1-maxlen)/2: (ct+maxlen)/2]
def preProcess(self, s):
n = len(s)
if n==0: return "^$"
res = "^"
for i in range(n):
res += '#'+s[i]
res += "#$"
return res
solution by dp in c++:
设f(i,j)表示字符串s[i...j]是否为回文字符串,那么状态转义方程如下:
if i==j or (i==j-1 and s[i]==s[j]) then f(i,j)=true
else if s[i]==s[j] and f(i+1, j-1)==true then f(i,j)=true
else f(i,j)=false
class Solution {
public:
string longestPalindrome(string s) {
if(s.size() < 2) return s;
int low=0, high=0;
int len = s.size();
vector<vector<bool> > dp(len, vector<bool>(len));
for(int i=len-1; i>=0; i--){
for(int j=i; j<len; j++){
if(i==j || s[i]==s[j] &&(i==j-1 || dp[i+1][j-1])){
dp[i][j] = true;
if(high-low < j-i){
high = j;
low = i;
}
}
}
}
return s.substr(low, high-low+1);
}
};
其他解法:以所有字母为中心,尽力向两端扩展找以该字母为中心可以形成的最大回文,在所有回文中找出最大的子串。复杂度O(n^2)