机房最后一个学习Manacher的人
Manacher大概就是利用回文子串的对称性来找到回文串长度下界不停往后递推
定义:
l
e
n
[
i
]
len[i]
len[i]表示
i
i
i为对称中心的最长回文长度,那么
l
e
n
[
i
]
−
1
len[i]-1
len[i]−1就是原串中的回文长度
m
x
mx
mx表示能扩展到的最右位置
p
o
s
pos
pos表示
m
x
mx
mx的回文子串的对称中心
步骤大概有这么几个:
1
、
1、
1、把原串中间插入一些奇怪的字符让它的回文子串长度都是奇数
2
、
2、
2、看
m
x
mx
mx是否比
i
i
i大,如果大就
l
e
n
[
i
]
=
m
i
n
(
m
x
−
i
,
l
e
n
[
2
∗
p
o
s
−
i
]
)
len[i]=min(mx-i,len[2*pos-i])
len[i]=min(mx−i,len[2∗pos−i])如果
m
x
mx
mx比
i
i
i小,则
l
e
n
[
i
]
=
1
len[i]=1
len[i]=1
3
、
3、
3、继续扩展
i
i
i
4
、
4、
4、更新
m
x
、
p
o
s
mx、pos
mx、pos
放个模板题luogu3805
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 11000005
using namespace std;
int len[maxn<<1];
char s[maxn],tmp[maxn<<1];
inline int init(char *p){
int n=strlen(p);
tmp[0]='@';
for(int i=1;i<=2*n;i+=2){
tmp[i]='#',tmp[i+1]=p[i/2];
}
tmp[2*n+1]='#'; tmp[2*n+2]='$';
return 2*n+1;
}
inline int Manacher(char *p,int n){
int mx=0,pos=0,ans=0;
for(int i=1;i<=n;i++){
if(mx>i) len[i]=min(mx-i,len[2*pos-i]);//i被mx覆盖了
else len[i]=1;
while(p[i-len[i]]==p[i+len[i]]) len[i]++;//左右扩展
if(len[i]+i>mx) mx=len[i]+i,pos=i;//更新
ans=max(ans,len[i]-1);
}
return ans;
}
int main(){
scanf("%s",s); int m=init(s);
printf("%d\n",Manacher(tmp,m));
return 0;
}

本文深入讲解Manacher算法,一种高效查找字符串中所有回文子串长度的方法。通过利用回文子串的对称性,算法能在O(n)时间内解决原本复杂度较高的问题。文章详细解释了算法步骤,包括字符串预处理、状态转移方程及模板代码。

8728

被折叠的 条评论
为什么被折叠?



