manacher/马拉车常用用法一览

因为manacher算法把原来的字符串扩大了两倍,因此在应用时许多二级结论都非常不直观,现场推出来很麻烦,因此笔者在此做个简单整理,如果发现有错误或者有常用的我没有涉及到的,恳请在下方评论区指出,我会非常感谢。

#include<iostream>
#include<cstdio> 
#include<cstring>
#define MAXN 200005
using namespace std;
char str[MAXN];
char ex[MAXN*2];
int rad[MAXN*2];
void make_char(const char *str,char *ex){
    int l=strlen(str);
    int i,j;
    j=0;
    ex[0]='$';
    for(i=0;i<l;i++){
        ex[++j]='#';
        ex[++j]=str[i];
    }
    ex[++j]='#'; 
    ex[++j]='';
}
int manacher(const char *ex,int *rad){
    int l1=strlen(ex);
    int mx=0,id=0,i=0;
    int maxx=0;
    rad[0]=0;
    for(i=1;i<l1;i++){
        if(i>=mx)rad[i]=1;
        else rad[i]=min(mx-i+1,rad[2*id-i]);
        while(ex[i-rad[i]]==ex[i+rad[i]]){
            rad[i]++;
        }
        if(i+rad[i]-1>mx){
            id=i;
            mx=i+rad[i]-1;
        }
        maxx=max(maxx,rad[i]-1);
    }
    return maxx;
}
int main(){
    scanf("%s",str);
    make_char(str,ex);
    printf("%d
",manacher(ex,rad));
    return 0;    
}

1,rad数组虽然指的是回文半径,但是它的值减一和回文子串长度对应

因此,最长回文子串长度是

max(ans[i]-1)

2,怎么对应呢,引入一个“某位置在ex上对应位置”概念

str[i]对应于ex[2i+2]

str[l,r]对应于ex[2*l+2,2*r+2]

ex[l+r+2]是该子串在ex上的中点

要问str上的子串[l,r]是不是回文子串

只需判断rad[l+r+2]-1>=r-l+1即可

3,假设t是str上某个点,t为整数时此点为某个字符,t不是整数时夹在两个字符串中间

那么以t为中点的最长回文子串的长度是rad[ans[2t+2]]-1

令tmp=rad[ans[2t+2]]-2

对应到str上的字符串是str[t-(tmp/2),t+(tmp)/2)

4,子串的回文子串

对于子串str[l,r]

将ans[2l+1,2r+3]如此构造:

ans'[i]=min(ans[i],l-i+1,r-i+1)

配合数据结构食用更佳

原文地址:https://www.cnblogs.com/isakovsky/p/11259351.html