解决最长回文子字符串问题——参考例题:力扣 .5
算法思路:首先定义变量:(创建数组rd)记录每一个位置上的最长回文子字符串的长度,设定当前最大回文子字符串的中心位置pos,对应的最右边界mx。
当到达位置 i 处,分两大类讨论:
1、当 i >mx,那么直接外扩查找回文子字符串
2、i 位置在目前的最右边界内,即 i < mx, 找到对位置 i' (pos-(i-pos)),根据之前记录的rd数组,判断i对应的回文子字符串多长。具体判断分3种情况:
1)i ' 对应的回文字符串在目前最大回文子字符串内部,那么rd[i]=rd[i'];
2) i ' 对应的回文字符串有一部分在目前最大回文子字符串外部,那么rdmx-i;
3)第三种,刚好与目前最大会文字字符串重合,那么就外扩查找。
其中1),2)可以合并在一起。
代码如下:
class Solution {
public:
string longestPalindrome(string s) {
int n=s.size();
string res="%#"; //避免越界
for(int i=0;i<n;i++)
{
res+=s[i];
res+='#'; //将字符串长度变成偶数
}
vector<int>rd(res.size(),0);
int pos=0,mx=0;//当前最大回文子字符串的中心位置,最右边界
int start=0,maxlen=0;//最大子字符串的起点位置,最大长度
for(int i=1;i<res.size();i++){
rd[i]=i<mx?min(rd[2*pos-i],mx-i):1; //当i的位置在当前最大回文串右边界左边的时候,两种情况合并写在一起
while(i+rd[i]<res.size()&&i-rd[i]>0&&res[i+rd[i]]==res[i-rd[i]]) //向外扩展
{
rd[i]++;
}
if(i+rd[i]>mx){
pos=i;
mx=rd[i]+i;//更新最大回文半径,还有对应的中心位置
}
if(rd[i]-1>maxlen){
start=(i-rd[i])/2;
maxlen=rd[i]-1; //计算最大回文子串的起始位置和半径长度
}
}
return s.substr(start,maxlen);
}
};