马拉车(Manacher)算法(求最大回文子串)

马拉车(Manacher)算法能够在O(n)的时间复杂度内找到字符串中的最大回文子串。该算法利用回文串的对称性进行剪枝优化,适用于奇偶长度的字符串。推荐观看相关B站视频辅助理解,并提供了博客链接供深入学习。

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

马拉车(Manacher)算法是一种时间复杂度为O(n)的求字符串中的最大回文子串的算法,
他很好的利用了回文串是关于中间字符对称的特点进行了剪枝操作,把时间复杂度优化到了O(n),并且它可以无差别处理奇偶字符串。

墙裂建议配合B站视频食用

UESTCACM 每周算法讲堂 manacher算法1(原理和思想)
UESTCACM 每周算法讲堂 manacher算法2(代码与实现)

我比较推荐看下面那个代码与实现,对着题边敲边讲,还是挺容易理解,如果看了这两个视频还是不理解的话,那就看看这个博客吧 —> Manacher Algorithm 马拉车算法(感谢博主) <— 或者也可以先看这个博客再去看视频。

其实最关键的就是下面的这些
在这里插入图片描述
图一
在这里插入图片描述
 图二
 
 一、mx > i 
  假设当前遍历到字符串的位置i,由于在遍历到id位置的时候已知最大回文子串,位置i还在上一个最大回文子串的范围内,所以可以利用其镜像认为,位置i以id为中心镜像到另一边的位置j是对等的。 在mx>i的条件下,又分为以下两种情况:
  1. mx - i > p[j] (图1)
  此时,以j为中心的回文子串包含在以id为中心的回文子串内,由于i和j位置对等,所以以i为中心的回文子串包含在以id为中心的回文子串内,所以p[i] = p[j] = p[2 * id - i]。
  2. mx - i <= p[j] (图2)
  此时,以j为中心的回文子串超过了以id为中心的回文子串边界,但是由于i和j位置对等,绿框部分还是相同的。所以其向右延伸的范围最大就是mx-i,剩下超过的部分谁也不能保证是否一致,只能通过循环对比判断,所以p[i] = mx - i。
 二、mx < i 
  此时镜像对预判位置起不到作用,只能从长度为1开始对比,所以p[i] = 1。

然后我就直接附上板子了。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 3e3;
char s[maxn],str[maxn];
int len1,len2,p[maxn];

void manacher()
{
    int id = 0,mx = 0;
    for(int i = 1; i < len2; i++)
    {
        if(mx > i) p[i] = min(p[2*id-i],mx-i);
        else p[i] = 1;
        for(; str[i+p[i]] == str[i-p[i]]; p[i]++);
        if(p[i] + i > mx)
        {
            mx = p[i]+i;
            id = i;
        }
    }
}

void init()
{
    str[0] = '$';
    str[1] = '#';
    for(int i = 0; i < len1; i++)
    {
        str[i*2+2] = s[i];
        str[i*2+3] = '#';
    }
    len2 = len1*2+2;
    str[len2] = '*';
}

int main()
{
    int n;
    cin >> n;
    while(n--)
    {
        cin >> s;
        len1 = strlen(s);
        init();
        manacher();
        int ans = 0;
        for(int i = 0; i < len2; i++)
        {
            ans = max(ans,p[i]);
        }
        cout << ans-1 << endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值