manacher算法 poj3974最长回文子串

题意:给一个字符串,求出它的最长回文子串的长度

这个hash+二分也能做,不过manacher比hash的那种方式代码简单点,而且效率高很多

一个几千毫秒,一个几百毫秒

马拉车的介绍https://blog.csdn.net/dyx404514/article/details/42061017

这博客写得有水平有质量。我刚刚开始的时候没有看懂if(mx>i)的部分

因为mx后面的没有求出,所以要保证len[i]小于mx,如果len[i]实际上是大于mx-i的,那么后面的while再更新len[i],并且考虑对称性,如果mx>i,len[i]一定是小于等于len[op*2-i]。

在设置边界的时候,左右边界的字符不能一样。

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<map>
using namespace std;
char s[1000005],ts[2000050];//转换后的数组是2n+1的长度
int n,len[2000005];
void trans()
{
    n=strlen(s+1);//s+1,而不是s,从s+1开始输入的字符串
    int i=0;
    ts[0]='@';//设置一个边界,防止越界
    for(i=1;i<=2*n;i+=2)
    {
        ts[i]='#';
        ts[i+1]=s[(i+1)/2];//插入#
    }
    ts[2*n+1]='#';
    ts[2*n+2]='$';//数组后面的边界
    ts[2*n+3]=0;
}
int manacher()
{
    int MAX=0,op=0,i,ans=0;//MAX是前面回文子串的最右边
    for(i=1;i<=2*n+1;i++)//op是有右边界MAX的回文子串中心的下标
    {
        if(MAX>i)
        {
            if(MAX-i>len[2*op-i])
            len[i]=len[2*op-i];
            else len[i]=MAX-i;
        }//取MAX-i和i关于op对称的len的最小值
        //不让i现在超过MAX,并且在op-MAX到op+MAX都是回文,保证对称性
        else len[i]=1;//从头开始
        while(ts[i-len[i]]==ts[i+len[i]])//回文子串从i往外扩展
        len[i]++;
        if(MAX<len[i]+i)
        {
            MAX=len[i]+i;
            op=i;
        }//更新MAX和op
        if(ans<len[i]-1)ans=len[i]-1;
    }
    return ans;
}
int main()
{
    int i,cas=0,a;
    while(scanf("%s",s+1)==1)//从s+1开始输入
    {
        if(s[1]=='E')break;
        trans();
        a=manacher();
        printf("Case %d: %d\n",++cas,a);
    }
    return 0;
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值