小白能懂的Manacher算法从入门到弃坑(马拉车)
马拉车详讲:
1.趣味图片讲解,有助于纯小白理解马拉车原理
可以点我哦QAQ
2.有助于有点基础的小白理解马拉车原理并写出代码
可以点我哦OAO
马拉车刷题:
1.马拉车模板题(入门)
#include<bits/stdc++.h>
#include<cstdio>
#define ll long long
using namespace std;
const int MMAX=11000005;
char st[2*MMAX];
char s[MMAX];
int le[MMAX*2];
int main()
{
scanf("%s",s);
int len=strlen(s);
st[0]='@';//字符串开头增加一个特殊字符,防止越界
for(int i=1;i<=2*len;i+=2)
{
st[i]='#';
st[i+1]=s[i/2];
}
st[len*2+1]='#';
st[len*2+2]='$';//字符串结尾加一个字符,防止越界
st[len*2+3]=0;
int mx=0,po=0,ans=0;
//mx为之前计算中最长回文子串的右端点的最大值,并且设取得这个最大值的位置为po
for(int i=1;i<=len*2+1;i++)
{
/**-----这一段可以仔细钻研一下-------*/
if(mx>i) le[i]=min(le[2*po-i],mx-i);
else le[i]=1;
while(st[i-le[i]]==st[i+le[i]]) le[i]++;
/**-------------------------------------*/
if(le[i]+i>mx)//更新mx和po
{
mx=le[i]+i;
po=i;
}
ans=max(ans,le[i]);
}
printf("%d\n",ans-1);//注意最后结果是ans-1
return 0;
}
2.复杂一点点的马拉车
#include<bits/stdc++.h>
#include<cstdio>-*
using namespace std;
const int MMAX=5005;
char st[2*MMAX],s[MMAX],temp[MMAX];
int le[2*MMAX];
int main()
{
int t; scanf("%d",&t);
while(t--)
{
int c1,c2,c3,c4,c5;
scanf("%s",s);
int len=strlen(s);
int l=0,r=len-1;
///先寻找前缀后缀相等的
while(r-l>=0&&s[r]==s[l]) l++,r--;
c1=l,c2=r;c3=len;
if(r-l<=0) printf("%s\n",s);
else {
///然后对剩余的字符串跑一边马拉车
for(int i=l;i<=r;i++) temp[i-l]=s[i];
temp[r-l+1]=0;
st[0]='@';
int ll=strlen(temp);
for(int i=1;i<=2*ll;i+=2)
{
st[i]='#';
st[i+1]=temp[i/2];
}
st[2*ll+1]='#';
st[2*ll+2]='$';
st[2*ll+3]=0;
int mx=0,ans=0,po=0,fm=0,f=-1;
///f=1记录是从左边开始,f=2记录从右边开始的,fm是回文串长度
for(int i=1;i<=2*ll+1;i++)
{
if(mx>i) le[i]=min(mx-i,le[2*po-i]);
else le[i]=1;
while(st[i-le[i]]==st[i+le[i]]) le[i]++;
if(le[i]+i>mx)
{
mx=le[i]+i;
po=i;
}
/**-------更新fm和f----------------------------*/
if(le[i]==i)
{
if(le[i]-1>fm)
{
fm=le[i]-1;
f=1;
}
}
else if(le[i]+i==ll*2+2)
{
if(le[i]-1>fm)
{
fm=le[i]-1;
f=2;
}
}
/**----------------------------------------------*/
}
for(int i=0;i<c1;i++) printf("%c",s[i]);
if(f==1)
{
for(int i=0;i<fm;i++) printf("%c",temp[i]);
for(int i=c2+1;i<c3;i++) printf("%c",s[i]);
printf("\n");
}
else
{
for(int i=c2-fm+1;i<len;i++)
printf("%c",s[i]);
printf("\n");
}
}
}
return 0;
}