最长回文字串-manacher算法

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>


using namespace std;
const int MaxSize = 1001;
#define min(a, b) ((a) < (b) ?(a) : (b));


void Manacher(char *str,int *p)
{
    int id;
    int mx = 0;
    int len = strlen(str);
    for(int i = 0;i < len;i++)
    {
        if(mx > i)
        {
            p[i] = min(p[2 * id - i],p[mx - i]);
        }


        else
        {
            p[i] = 1;
        }


        for(;(str[p[i] + i] == str[p[i] - i]);p[i]++);
        if(p[i] + i > mx)
        {
            mx = p[i] + i;
            id = i;
        }
    }
}


注:


if(mx > i) p[i]= min(p[2 * id - i], mx -i);
这是代码中最核心的一句话,它的作用是让我们在以i为中心向左右扩展时,尽量减少重复的比较,当mx > i 时会有两种情况。设j = 2 *id – i  以id为中心i的对称位置。
第一:当以i为中心的回文和以j为中心的回文都在以id为中心的回文中时。
 由于回文的对称性,这时p[i]最小为p[j] 这是表达式前半部分。
第二:当以i为中心的回文或以j为中心的回文不在以id为中心的回文中时。
        q a b a c a b a c
             j   id   i
或:
c a b a c a b q c
    j  id   i
这时以i为中心的最长回文不一定大于p[i],但是由于回文的对称性,他最小是mx-i(p[j]大时)或p[j]。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值