[模板]manacher算法

本文介绍了一种高效算法——Manacher算法,用于在给定的字符串中寻找最长的回文子串。通过预处理字符串并利用已知的回文特性,该算法能够在O(n)的时间复杂度内解决问题。

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

给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
字符串长度len <= 11000000

题目来源:Luogu P3805

我们就假设长度为 n 吧,字符串为S,最长回文串为 ans
先说一下几个显然的算法:

O(n3) 暴力

直接枚举所有 i[1,n) j(i,n] ,判断回文
判断方法就是枚举 k[0,ji2]
若存在 k ,使Si+kSjk,则 S 非回文串,否则S为回文串

O(n2) 暴力

分两种情况讨论:

2ans

显然枚举所有 i[1,n]
枚举 j[1,min{i,ni}) 找到第一个 Si+jSij
2j+1 更新 ans

2ans

枚举所有 i[1,n)
枚举 j[0,min{i,ni1}) 找到第一个 SijSi+j+1
2j+2 更新 ans

前方高能!!!

manacher

复杂度 O(n)
网上是这样说的,可是我感觉不止啊
假设有一个字符串长这样:
abacab
我们先给它做个处理:
$#a#b#a#c#a#b#
设处理后的串为 C ,最长回文串为c
这样有两个好处:

不用管偶数长度的回文
不用管边界

也有些性质:

c=2ans+1

我们需要记录两个东西: max,p 分别为当前搜到的最靠右的位置,和搜到那个位置的回文串中心。
f(i) 表示以 i 为中心的最长回文串
因为是顺次搜,所以必定会有p<i
根据 max,p 的定义,有 p<max
我们假设有以下数量关系:

i<max

因为 C 的区间[2pmax,max]是关于 p 对称的
所以f(i)f(2pi)我们可以在 i f(2p1)的基础上向两边扩张

imax

没搜到的有木有,所以像 O(n2) 暴力一样扩张
然后要搞大事啦:
p=i,max=i+f(i) 没错,更新不可少
附代码:

#define N 11000010
int len,g[2*N],f[2*N],m,p,ans;
int main(){
    char c=gc;
    while(c<'a'&&c>'z')
        c=gc;
    g[0]=27;
    while(c>='a'&&c<='z')
    {
        len+=2;
        g[len]=c-'a'+1;
        c=gc;
    }
    len++;
    fr(i,1,len)
    {
        if(i<m)
            f[i]=min(m-i,f[p+p-i]);
        else
            f[i]=1;
        while(g[i+f[i]]==g[i-f[i]])
            f[i]++;
        if(i+f[i]>m)
        {
            m=i+f[i];
            p=i;
        }
    }
    fr(i,1,len)
        ans=max(ans,f[i]);
    printf("%d\n",ans-1);
    rt 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值