Manacher算法求最长回文子串

写在前面

本文不是写给完全没接触过的小白看的,是自己对Manacher算法的一些理解和总结,主要是写给自己看的。
如果你已经学会或者看了其他的教程没明白的,可以来看看咱的这篇文章。


Manacher算法

利用回文字符串的特性,在O(n)的时间复杂度下求取以每个字符为中心的最长回文子串长度的数组。


核心思想

在求以 s[i]为中心的最长回文子串的过程中,可以直接取 p[i] = p[i_mirror]。(s[i_mirror]是s[i]关于s[Center]的对称点)


对上面这句话的解释

以回文串 s = "a b a b f b a b a b a" 为例:

整个串以 'f'为中心有最长回文子串 s[0] ~ s[8] = "a b a b f b a b a"

在求p[6]时,可以直接取p[4] = p[2]

因为以s[2] = 'a'为中心的最长回文子串是 s[1] ~ s[3] = "a b a"s[1] ~ s[3]在以s[4] = 'f'为中心的回文子串的左边界,那也就是说在s[4]的右边一定有s[5] ~ s[7] = "a b a",也就是说p[6]可以直接取p[2]的值。


几种情况还需要继续拓展

可以看到,以上成立的条件一定是左右两段区间在一个大的回文串的左右两侧。

所以当前位置i复制了i_mirror的值之后,还可以继续超过大的回文串的的右边界向两侧拓展的时候,就需要更新当前的大的回文串,使得当前选定的大的回文串包含当前的位置i,即更新CR的值。

或者当前位置i直接超出了R的边界,没有任何东西可以参考,则置p[i] = 0,从0开始拓展。


代码

#include <bits/stdc++.h>

using namespace std;

string pre_process(const string& s) {
    string ret("^#");
    for (char c : s) {
        ret.append(1, c);
        ret.append(1, '#');
    }
    ret.append(1, '$');
    return ret;
}

string Manacher(const string& s, const string& raw) {
    int len = s.size(), p[2010] = {}, C = 0, R = 0;
    for (int i = 1; i < len - 1; i++) {
        int i_mirror = 2 * C - i;
        if (R > i) {
            p[i] = min(R - i, p[i_mirror]); // 1.超出了R or 2.p[i_mirror]遇到了原字符串左边界
        } else {
            p[i] = 0;
        }

        while (s[i + p[i] + 1] == s[i - p[i] - 1]) {
            p[i]++;
        }

        if (i + p[i] > R) {
            C = i;
            R = i + p[i];
        }
    }

    int ct_idx = max_element(p, p + len) - p;
    int start = (ct_idx - p[ct_idx]) / 2;
    return raw.substr(start, p[ct_idx]);
}

int main() {
    string s;
    cin >> s;
    string ss = pre_process(s);
    string palindromic = Manacher(ss, s);
    cout << palindromic << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值