马拉车算法模板

模板来源:HKer_YM的博客
1.求最长回文长度或回文子串个数

//求回文串的个数
inline int Manacher(string s)
{
    //转换字符串
    memset(hw, 0, sizeof(hw));
    int len = s.length();
    string nowString = "$#";
    for(int i = 0; i < len; i++){
        nowString += s[i];
        nowString += "#";
    }
    //防止越界访问
    nowString += "^";
    len = nowString.length();
    int maxRight = 0, mid = 0, maxAns = 0, numAns = 0;
    //maxRight 最右边的位置 mid 中心的位置 maxAns 最长回文串的半径
    for(int i = 1; i < len; i++){
        if(maxRight > i){
            //当中心点没超过最右边maxRight
            hw[i] = min(maxRight - i, hw[(mid<<1) - i]);
        }
        else{
            //否则,就重新往外扩
            hw[i] = 1;
        }
        //如果当前不是最长, 就往外扩
        while(nowString[i + hw[i]] == nowString[i - hw[i]]){
            ++hw[i];
        }
        //更新最右边的位置, 同时更新最长字串的半径
        if(i + hw[i] > maxRight){
            maxRight = i + hw[i];
            mid = i;
        }
        //求最长回文串的长度
        //maxAns = max(hw[i], maxAns);
        //求回文串的个数
        numAns += (hw[i] / 2);
    }
    //最长字串的长度等于半径减1
    //return (maxAns - 1);
    //回文串的个数
    return numAns;
}

2.求最长的回文子串

//求最长回文串
inline string Manacher(string s)
{
    //转换字符串
    memset(hw, 0, sizeof(hw));
    int len = s.length();
    string nowString = "$#";
    for(int i = 0; i < len; i++){
        nowString += s[i];
        nowString += "#";
    }
    //防止越界访问
    nowString += "^";
    len = nowString.length();
    int maxRight = 0, mid = 0, maxLen = 0, maxPoint = 0;
    //maxRight 最右边的位置 mid 中心的位置 maxAns 最长回文串的半径
    for(int i = 1; i < len; i++){
        if(maxRight > i){
            //当中心点没超过最右边maxRight
            hw[i] = min(maxRight - i, hw[(mid<<1) - i]);
        }
        else{
            //否则,就重新往外扩
            hw[i] = 1;
        }
        //如果当前不是最长, 就往外扩
        while(nowString[i + hw[i]] == nowString[i - hw[i]]){
            ++hw[i];
        }
        //更新最右边的位置, 同时更新最长字串的半径
        if(i + hw[i] > maxRight){
            maxRight = i + hw[i];
            mid = i;
        }
        if(hw[i] > maxLen){
            maxLen = hw[i];
            maxPoint = i;   //最长回文串的中心位置
        }
    }
    //截取最长回文串
    //这里为啥这样写,在本博客前文已经提到过: 1. 第一步,重组字符串
    return s.substr((maxPoint - maxLen) / 2, maxLen - 1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值