1.中心拓展法
由回文字符串的特征可知,该种字符串可以由中心向两边拓展,而需要我们去验证的中心点有2n+1个,因为对于长度为偶数的回文串来说,其中心点在两个字符之间:
class Solution {
public:
string longestPalindrome(string s) {
if(s.size()==1||s.size()==0) return s;
int start=0,end=0,l=0;
string ans;
for(int i=0;i<s.size();i++){
int len1=expand(s,i,i);
int len2=expand(s,i,i+1);
int len=max(len1,len2);
if(len>end-start){
start=i-(len-1)/2;
end=i+len/2;
l=len;
}
}
ans=s.substr(start,l);//从start开始长度为l
return ans;
}
int expand(string s,int left,int right){
int l=left,r=right;
while(l>=0&&r<s.length()&&s[l]==s[r]){
l--;
r++;
}
return r-l-1;//终止时i为回文串首字母前一个
}
};
2. 动态规划法
设置一个二维的动态规划数组dp,若dp[i][j]==1,则代表s[i]到s[j]是一个回文串
所以根据回文串的性质,对角线上的数组元素,dp[i][i]全都是1
dp[i][i+1]=dp[i][i] and (s[i]==s[i+1]);
根据以上性质,对数组进行初始化后,可以写出状态转移方程:
dp[i][j]=dp[i+1][j-1] and(s[i]==s[j]);
class Solution {
public:
string longestPalindrome(string s) {
int len=s.size();
if(len==0||len==1)
return s;
int start=0;//回文串起始位置
int max=1;//回文串最大长度
vector<vector<int>> dp(len,vector<int>(len));//定义二维动态数组
for(int i=0;i<len;i++)//初始化状态
{
dp[i][i]=1;
if(i<len-1&&s[i]==s[i+1])
{
dp[i][i+1]=1;
max=2;
start=i;
}
}
for(int l=3;l<=len;l++)//l表示检索的子串长度,等于3表示先检索长度为3的子串
{
for(int i=0;i+l-1<len;i++)
{
int j=l+i-1;//终止字符位置
if(s[i]==s[j]&&dp[i+1][j-1]==1)//状态转移
{
dp[i][j]=1;
start=i;
max=l;
}
}
}
return s.substr(start,max);//获取最长回文子串
}
};