To improve over the brute force solution, we first observe how we can avoid unnecessary re-computation while validating palindromes.
Consider the case ''ababa''. If we already knew that ''bab'' is a palindrome, it is obvious that ''ababa'' must be a palindrome
since the two left and right end letters are the same.
We define P(i,j)P(i,j) as following:
P(i,j)= | true,if the substring Si…Sj is a palindrome
| false,otherwise.
P(i,j)={true,if the substring Si…Sj is a palindrome;false,otherwise.
Therefore,
P(i, j) = ( P(i+1, j-1) && S_i == S_j )
The base cases are:
P(i, i) = true P(i,i)=true
P(i, i+1) = ( S_i == S_{i+1} )
This yields a straight forward DP solution, which we first initialize the one and two letters palindromes, and work our way up finding all three letters palindromes, and so on...
Complexity Analysis
Time complexity : O(n^2)
Space complexity : O(n^2)
*/
public class Solution {
public String longestPalindrome(String s) {
if(null == s || s.isEmpty()){
return "";
}
int len = s.length();
if(1 == len){
return s;
}
boolean[][] dpTab = new boolean[len][len];
int start = 0,end =0;
for(int i = 0 ;i<len;i++){
dpTab[i][i] = true;
if(i!=len-1){
dpTab[i][i+1] = s.charAt(i) == s.charAt(i+1);
if(dpTab[i][i+1]){
start = i;
end = i+1;
}
}
}
for(int step=3 ; step <= len;step++){
for(int i = 0;i < len-step+1;i++){
int j = i+step-1;
dpTab[i][j] = dpTab[i+1][j-1] && (s.charAt(i) == s.charAt(j));
if(dpTab[i][j]){
start = i;
end = j;
}
}
}
return s.substring(start,end+1);
}
}