class Solution {
public:
string longestPalindrome(string s) {
int n=s.size();
string ss;
ss+="$#";
// 预处理字符串,将每个字符前后插入#,处理奇数和偶数长度回文的统一问题
// 例如:s="abba" -> ss="$#a#b#b#a#^"
for(int i=0;i<n;i++){
ss+=s[i];
ss+='#';
}
ss+="^";
// d数组记录以每个位置为中心的最长回文半径
vector<int>d(ss.size()+1);
// 初始化第一个字符的回文半径(实际上是$后的#,半径为1)
d[1]=1;
// l和r分别记录当前已知的最右回文子串的左右边界
for(int i=2,l,r=1;i<ss.size();i++){
// 若当前位置i在最右边界r内,利用对称性初始化d[i]
if(i<=r) d[i]=min(r-i+1,d[r-i+l]);
// 尝试扩展以i为中心的回文半径(无论是否利用对称性)
while(ss[i-d[i]]==ss[i+d[i]]) d[i]++;
// 若当前回文右边界超过r,更新r和对应的左边界l
if(i+d[i]-1>r) l=i-d[i]+1,r=i+d[i]-1;
}
// 查找最大回文半径及其中心位置
int idx=-1,len=-1;
for(int i=1;i<=ss.size();i++){
if(d[i]>len){
len=d[i],idx=i;
}
}
// 将预处理后的中心位置和半径转换回原始字符串的索引
idx=(idx-len)/2;
// 返回原始字符串中的最长回文子串
return s.substr(idx,len-1);
}
};