Manacher(马拉车算法)

Manacher算法,又叫“马拉车”,它可以在时间复杂度和空间复杂度都是O(n)的情况下,求出一个字符串的最长回文串长度。

通过优化朴素诞生的一个算法

首先将字符拓展为固定形式例如abc拓展为:abc -> #a#b#c ->@#a#b#c%(@#%需为不存在的字符

然后就可以去除奇偶性,遍历字符进行回文拓展

需要通过一个数组存储每个字符的最大回文长度

主要依托回文的特性来优化朴素算法

图片来自:马拉车算法 | Coding Club

 在a的超大回文中,可以直接将左侧回文的复制到右侧,通过这种方法来优化朴素算法

主要分为三部

1,变换字符串:abc -> #a#b#c ->@#a#b#c%(@#%需为不存在的字符

2,用R和Mid记录目前最右侧的边界和中心

例如:

3,遍历字符串

        1》给p[i]赋初值:如果在最大的内部:

                                                        如果对称的范围不超过边界,就直接复制

                                                        如果超过边界,就赋值为距离边界的距离

                               如果不在内部:直接赋值为1(朴素算法)

       2》向两端拓展直到最大

        3》如果拓展后的边界大于R,就迭代R和Mid

4,最后将p里的数字减去1然后除以二((p[i]-1)/2)后就是该位置最大的回文长度了

注意:因为字符串初始化的时候头尾不一致,所以能自动结束

#include <bits/stdc++.h>

using namespace std;

string change(string s)
{
    string res = "@#";
    for(char c : s){res += c; res += "#";}
    res += "#$";
    return res;
}

void Manacher(string s,int *p)
{
    int R = 0,Mid = 0;
    for(int i = 0;i < s.size();++i)
    {
        p[i] = R > i ? min(p[2 * Mid - i],R-i) : 1;//给p[i]赋初值
        while(s[p[i] + i] == s[i - p[i]]) ++p[i];//向两端拓展直到最大
        if(p[i] + i > R)//如果拓展后边界大于R,就迭代R和Mid
        {
            Mid = i;
            R = p[i] + i;
        }
    }
}

int main()
{
    string s;
    cin >> s;
    s = change(s);
    int p[s.size()];
    Manacher(s,p);
    return 0;
}
  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值