马拉车算法

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);
    }
};
posted @ 2025-07-02 16:28  Qacter  阅读(9)  评论(0)    收藏  举报