Manacher

时间:2019-10-02
本文章向大家介绍Manacher,主要包括Manacher使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

/*
manacher是字符串最长回文子串算法,O(n)
对于一个字符串aaabba,最长回文子串是abba
对于一个回文子串一定有一个对称轴,如果想O(n)求出最长回文子串,我们只需枚举每个对称轴,然后O(1)递推即可
所以manacher的一个操作就是在所以中间的位置插入一个'#'之类的无用字符,这样我们可以忽略对称轴在两个字符中间的情况
而只考虑对称轴落在字符上的情况(上面的对称轴在ab之间,如果是按照对称轴为一个字符,比较好找)
定义Mp[i]表示以i为回文中心,半径为Mp[i]

*/

代码解释

定义

定义Mp[i]表示以i为回文中心,半径为Mp[i]大小为len<<1

定义Ma[]数组表示加了分隔符#之后的字符串大小len<<1

模板

传送门

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=11e6+5;
char str[maxn];
int Mp[maxn<<1];
char Ma[maxn<<1];//存放包含无用字符#的字符串
int len;
void Manacher(char str[],int len){
    int l=0;
    Ma[l++]='$';
    Ma[l++]='#';
    for(int i=0;i<len;i++){
        Ma[l++]=str[i];
        Ma[l++]='#';
    }
    Ma[l]=0;
    int mx=0,id=0;
    for(int i=0;i<l;i++){
        Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1;
        while(Ma[i+Mp[i]]==Ma[i-Mp[i]])Mp[i]++;
        if(i+Mp[i]>mx){
            mx=i+Mp[i];
            id=i;
        }
    }
}
int main(){
    while(~scanf("%s",str)){
        len=strlen(str);
        Manacher(str,len);
        int ans=0;
        for(int i=0;i<2*len+2;i++){
            ans=max(ans,Mp[i]-1);
        }
        printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Emcikem/p/11616789.html