【字符串 manacher】洛谷_3805 manacher算法

本文深入讲解Manacher算法,一种高效求解最长回文子串问题的方法。通过在字符串空隙中插入符号,处理偶数长度回文串,利用回文字符串的对称性加速计算。代码实现展示了如何枚举并更新回文串的边界,最终得出最长回文串的长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

求一个字符串中最长回文串的长度。

思路

manachermanachermanacher算法。

首先我们先在字符串空隙中插入符号,以便处理偶数长度的回文串。

hwihw_ihwi为以iii为中心最多能往旁边扩展的长度,maxrightmaxrightmaxright为当前匹配到的最右边的回文串。

枚举1∼n1\sim n1n,如果i&lt;maxrighti&lt;maxrighti<maxright且在midmidmid右边,那么根据回文字符串的对称性,可以知道它的对称点jjjhwj≤hwihw_j \leq hw_ihwjhwi,我们就可以直接用hwjhw_jhwj更新hwihw_ihwi,然后再扩展,要注意用hwjhw_jhwj来更新hwihw_ihwi不能使i+hwii+hw_ii+hwi超过maxrightmaxrightmaxright,因为不一定满足对成性。

如果i&gt;maxrighti&gt;maxrighti>maxright就从111开始来扩展。

如果扩展完后的位置&gt;maxright&gt;maxright>maxright,我们就可以更新它和midmidmid

答案就为max{hwi}−1max\{hw_i\}-1max{hwi}1,因为一开始我们在字符串空隙中插入了符号,所以不用∗2*22

代码

#include<cstdio>
#include<cstring>
#include<algorithm>

int n, ans;
int hw[22000002];
char a[11000000], s[22000002];

void init() {
    scanf("%s", a);
    s[0] = s[1] = '#';
    n = strlen(a);
    for (int i = 0; i < n; i++) {
        s[i * 2 + 2] = a[i];
        s[i * 2 + 3] = '#';
    }
    n = n * 2 + 2;
    s[n] = 0;
}

void manacher() {
    int maxright = 0, mid;
    for (register int i = 1; i < n; i++) {
        if (i < maxright)
            hw[i] = std::min(hw[mid * 2 - i], maxright - i);
        else hw[i] = 1;
        for (; s[i + hw[i]] == s[i - hw[i]]; hw[i]++);//扩展
        if (hw[i] + i > maxright) {//更新
            maxright = hw[i] + i;
            mid = i;
        }
        ans = std::max(ans, hw[i]);
    }
}

int main() {
    init();
    manacher();
    printf("%d", ans - 1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值