//第一种方法:动态规划dp
class Solution {
public:
string longestPalindrome(string s) {
int n=s.length();//s的长度 0-n-1
if(n<2)return s;//剪枝
int dp[1005][1005]={0};//设置hash表记录s[i][j]是否是回文串
// memset(dp,0,sizeof(dp))
//初始化长度为1的字符串都为1
for(int i=0;i<n;i++){
dp[i][i]=1;
}
int begin=0;//记录最长回文串开始的位置
int maxLen=1;//记录最长的长度
//最外层的循环枚举的是子串的长度
for(int L=2;L<=n;L++){
//i是左边界 j是右边界
for(int i=0;i<n;i++){
//从左边开始迭代,每次在一轮内找到最长的maxLen
int j=i+L-1;
//对j的边界进行检查
if(j>=n)break;
if(s[i]==s[j]){
if(j-i<3){//说明长度是3以内的,由于L=1是回文,而s[i]==s[j],则是回文
dp[i][j]=1;
}
else{
//状态转移方程
dp[i][j]=dp[i+1][j-1];
}
}
if(j-i+1>maxLen && dp[i][j]==1){
maxLen=j-i+1;
begin=i;
}
}
}
return s.substr(begin,maxLen);//(开始,长度)
}
};
//2.中心点扩展法
class Solution {
public:
string longestPalindrome(string s) {
int n=s.length();
if(n<2)return s;
//中心拓展法
string ans=s.substr(0,1);//存储中间的结果
//中心点遍历,中心点排除头尾其中一个
for(int i=0;i<=n-2;i++){//全排除的话会有"bb"这种字符串
//分为奇数的回文和偶数的回文
string res=getMaxS(i,i,s);//奇数的回文从getMaxS(i,i,s)
if(res.length()>ans.length())ans=res;
res=getMaxS(i,i+1,s);//偶数的回文从getMaxS(i,i+1,s)
if(res.length()>ans.length())ans=res;
}
return ans;
}
//从中心点开始向外拓展,得到最大的回文子串
string getMaxS(int left,int right,string s){
int n=s.length();
while(left>=0 && right<=n-1 && s[left]==s[right]){
left--;
right++;
}
return s.substr(left+1,(right-1)-(left+1)+1);
}
};