From : https://leetcode.com/problems/longest-palindromic-substring/
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.
Solution 1 :
动态规划。 isPalin 表示i到j之间是否是回文,时间O(n^2), 空间O(n^2)。
class Solution {
public:
string longestPalindrome(string s) {
if(s == "") return "";
int len=s.size(), start=0, end=0;
bool isPalin[len][len];
// init
for(int i=0; i<len; i++) {
for(int j=0; j<=i; j++) {
isPalin[i][j] = true;
}
for(int j=i+1; j<len; j++) {
isPalin[i][j] = false;
}
}
// core
for(int j=1; j<len; j++) {
for(int i=0; i<j; i++) {
if(s[i] == s[j]) {
isPalin[i][j] = isPalin[i+1][j-1];
if(isPalin[i][j] && j-i > end-start) {
start = i;
end = j;
}
}
}
}
return s.substr(start, end-start+1);
}
};
Solution 2:
回文有中心,遍历这些中心。时间O(n^2),空间O(1)。
class Solution {
public:
void expendFromCenter(string &str, int i) {
int st, ed;
ed = (i>>1)+1;
st = ed - 1 - (!(i&1));
while(st >= 0 && ed < length && str[st] == str[ed]) {
st--; ed++;
}
st++; ed--;
if(ed - st > end - start) {
start = st;
end = ed;
}
}
string longestPalindrome(string s) {
if((length = s.size()) <= 1) return s;
start = end = 0;
for(int i=0, n=2*length-1; i<n; i++) {
expendFromCenter(s, i);
}
return s.substr(start, end-start+1);
}
private:
int start, end, length;
};
剪枝处理,求取可扩展的半径r,只对可能的情况做处理,半径超出字符串界或者半径边界本身不相等,那么不可能成为更长的回文,剪枝。
class Solution {
public:
int find(string& s, int c, int& st, int& ed, int& len) {
int i, j;
if(c&1) {
i = c>>1;
j = i+1;
} else {
i = (c>>1)-1;
j = i+2;
}
int r = (ed-st-j+i+1)>>1;
if(i-r < 0 || j+r >= len || s[i-r] != s[j+r]) {
return r;
}
while(i>=0 && j<len && s[i] == s[j]) {
if(j-i > ed-st) {
st = i;
ed = j;
}
--i;
++j;
}
return r;
}
string longestPalindrome(string s) {
if(s.size() <= 1) return s;
int start = 0, end = 0, len = s.size();
int centers = len+len-1;
for(int i=1, r=0; i<centers-r; ++i) {
r = find(s, i, start, end, len);
}
return s.substr(start, end-start+1);
}
};
Solution 3:
Manacher’s Algorithm算法,详见
http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html
http://www.felix021.com/blog/read.php?2040
根据回文的对称性,选出最大回文。
class Solution {
public:
// Transform S into T.
// For example, S = "abba", T = "^#a#b#b#a#$".
// ^ and $ signs are sentinels appended to each end to avoid bounds checking
string preProcess(string &s) {
int n = s.length();
if (n == 0) return "^$";
string ret = "^";
for (int i = 0; i < n; i++)
ret += "#" + s.substr(i, 1);
ret += "#$";
return ret;
}
string longestPalindrome(string s) {
string T = preProcess(s);
int n = T.length();
int *P = new int[n];
int C = 0, R = 0;
for (int i = 1; i < n-1; i++) {
int i_mirror = 2*C-i; // equals to i' = C - (i-C)
P[i] = (R > i) ? min(R-i, P[i_mirror]) : 0;
// Attempt to expand palindrome centered at i
while (T[i + 1 + P[i]] == T[i - 1 - P[i]])
P[i]++;
// If palindrome centered at i expand past R,
// adjust center based on expanded palindrome.
if (i + P[i] > R) {
C = i;
R = i + P[i];
}
}
// Find the maximum element in P.
int maxLen = 0;
int centerIndex = 0;
for (int i = 1; i < n-1; i++) {
if (P[i] > maxLen) {
maxLen = P[i];
centerIndex = i;
}
}
delete[] P;
return s.substr((centerIndex - 1 - maxLen)/2, maxLen);
}
};