case1:使用dp思想
dp[start][end] 表示字符串s的[start,end]区间是否为回文串
状态转移方程:
dp[start][end] = curLen==1||(curLen==2||dp[start+1][end-1])&&s.charAt(start)==s.charAt(end)
怎么理解这个状态转移方程: 长度为1的串或者长度为2且首尾相同的串或者符合中心扩延的串均为回文串
时间复杂度为O(n ^ 2),空间复杂度O(n^2)
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if(len<=1)return s;
boolean[][]dp = new boolean[len][len];
int finalLeft = 0,finalRight = 0,maxLen = 0;
//穷举串s的所有长度的子串
for(int curLen=1;curLen<=len;curLen++){
for(int start=0;start<len;start++){
int end = start+curLen-1;
if(end>=len) continue;
//判断其是否为回文串
dp[start][end] = (curLen==1)||(curLen==2||dp[start+1][end-1])&&s.charAt(start)==s.charAt(end);
if(dp[start][end]){
if(end-start+1>maxLen){
maxLen = (end-start+1);
finalLeft = start;
finalRight = end;
}
}
}
}
return s.substring(finalLeft,finalRight+1);
}
}
case2:使用中心扩延定理,长度为n的串中心有2n+1个
时间复杂度为O(n^2),空间复杂度为O(1)
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if(len<=1)return s;
int centerCounts = 2*len + 1;
int finalLeft = 0,finalRight = 0;//分别指向最终找到最长回文子串的左端点和右端点
for(int cid=0;cid<centerCounts;cid++){
int left = (cid / 2) ,right = left + (cid % 2);
while(left>=0&&right<len&&s.charAt(left)==s.charAt(right)){
left--;
right++;
}
if((right-left-1)>(finalRight-finalLeft+1)){
finalLeft = left+1;
finalRight = right-1;
}
}
return s.substring(finalLeft,finalRight+1);
}
}
上面两种方法都会找出当前字符串s的所有回文子串,所以它们还可以用来求字符串s的回文子串总数或者找出所有的回文子串