三种方法
1.暴力通过剪枝可以达到O(n^2)的时复
2.二维dp,此处需要用到二维dp,dp[i][j]存的是以i为头,j为首的字符串是否为回文串。根据回文串的性质来写转移方程。1.回文串两头相等。2.回文串去掉头尾还是回文串。我们用maxLen和begin来记录子串的起始位置和最大长度,不要每次都substr。因为这里是二维dp,二维dp最最重要的就是填表顺序,这里我的填表方式是一列一列填表,因为dp[i][j]要根据dp[i+1][j-1]来推断,刚好是左下角,所以一列一列填表是可以,而且只要填右上角部分就行。j从第1列开始,不是第0列,因为0,0一定是true,i从第0遍历到j-1,如果首尾不等,dp[i][j]就是false,如果相等,判断j-i+1是否<=3,也就是该子串的长度,如果小于3且首尾相等,那就是一个回文串。如果不<=3就根据左下角来判断。判断完dp[i][j]完后判断maxlen和j-i+1哪个大。时复和空复均为O(N^2)
3.中心扩散法:时复O(n^2),空复O(1)。遍历s每一位,将它往两边扩散(直到找到以它为中心不是回文串为止),left=i-1,right=i+1,如果s[left]==s[i]就将left–,right类似,直到找不到不等的。因为如果是相等的,aaaa不管几个a都是回文串。根据左右扩散,如果左右相等,就一直扩散。注意的是left和right的操作每一步都要判断是否越界。在left–和right++时都要将tmpLen加1,两边扩散时+2。最后判断的时候left+1才是真正的begin位,因为left已经构不成回文串了。
class Solution {
public:
string longestPalindrome(string s) {
//最长=最优解=dp
if(s.length() < 2) return s;
int n = s.length();
//string res = "";
//暴力,遍历i位,每次截取j位,记录最长的回文子串,通过reverse来判断,先暴力再考虑dp
/*for(int i = 0; i < s.length(); ++i){
for(int j = i; j < s.length(); ++j){
string tmp = s.substr(i,j-i+1);
string rev = tmp;
reverse(rev.begin(),rev.end());
if(tmp == rev && j-i+1>res.length()){
res = tmp;
}
}
}
return res;*/
//此处需要用二维dp,通过回文子串的特性来推断状态转移方程
//1.回文串两头相等。2.回文串去掉头尾还是回文串
//dp[i][j]存的是以i为头,j为首的字符串是否是回文串
//状态转移方程:dp[i][j]=
//1.如果s[i]==s[j],dp[i][j]=dp[i+1][j-1],要从短判断到长,需要一列一列填表
/*int maxLen = 1;
int begin = 0;
vector<vector<bool>> dp(n,vector<bool>(n));
for(int j = 1; j < n; ++j){
for(int i = 0; i < j; ++i){
//不用i==j,因为dp[i][i]一定是回文,不用判断
if(s[i] != s[j]){
dp[i][j] = false;
}
else if(s[i] == s[j]){
if(j-i+1<=3){
dp[i][j] = true;
}
else{
//不用判断越界,i+1最大等于j,j-1最小等于0
dp[i][j] = dp[i+1][j-1];
}
}
if(dp[i][j]&&j-i+1>maxLen){
begin = i;
maxLen = j-i+1;
}
}
}
return s.substr(begin,maxLen);*/
//中心扩散法
int left = 0, right = 0, maxLen = 1, begin = 0;
for(int i = 0; i < n; ++i){
left = i-1;
right = i+1;
int tmpLen = 1;
while(left>=0 && s[i] == s[left]){
tmpLen++;
left--;
}
while(right<n && s[i] == s[right]){
tmpLen++;
right++;
}
while(left>=0 && right<n && s[left] == s[right]){
left--;
right++;
tmpLen+=2;
}
if(tmpLen>maxLen){
//应该是left+1,因为此时的left已经不是回文子串了
begin = left+1;
maxLen = tmpLen;
}
}
return s.substr(begin,maxLen);
}
};