Manacher学习笔记
1.介绍:
manacher算法用于求解回文子串问题,可以求出以一个串中每一点为中心的最长回文半径,相当于可以求出所有回文子串
2.引入:
假如要求出一个串所有长度为奇数的回文子串,暴力怎么做?
枚举以每个点为回文中心,向两侧扩展,分别比较a[p+i]与a[p-i]
时间复杂度 O(n^2)
我们考虑优化,我们可以利用已经求解出的回文子串的信息
- 举例:a a b c b a b c
考虑回文中心在i之前的、最右端最远的一个回文子串
可以看出,在求解第7位b的回文半径时,我们是可以利用到第3位b的数据的
- 当然,有的时候需要注意一下
此时就要注意,不能直接利用3,而是要与最远的那个回文子串进行一个比较
因此,我们只需要记下来当前右端最远的回文子串,就可以先利用之前的信息跳过一部分试验
当然,在利用过后,还需要继续用暴力的方法拓展
对了,现在只求出了所有长度为奇数的回文子串,那么长度为偶数的怎么办?
在每两个字符之间插入特殊字符即可
例如aabbaa -> #a#a#b#b#a#a#
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 11000010
int cnt;
int len;
char s[maxn],s_[maxn*2];
int f[maxn*2];
void make()
{
cnt=2;
s_[0]='^';
s_[1]='$';
for(int i=0;i<len;i++)
{
s_[cnt++]=s[i];
s_[cnt++]='$';
}
s[cnt]='&';
}//世界第一甜
void Manacher()
{
int mid=0,ans=0,ma=0;
for(int i=1;i<=(len*2+1);i++)
{
if(ma>i)
{
f[i]=min(ma-i,f[mid*2-i]);
}
else
{
f[i]=1;
}
while(s_[i-f[i]]==s_[i+f[i]])
{
f[i]++;
}
if(ma<(i+f[i]))
{
ma=i+f[i];
mid=i;
}
ans=max(ans,f[i]);
}
printf("%d\n",ans-1);
return;
}//华锐李泽言
int main()
{
scanf("%s",s);
len=strlen(s);
make();
Manacher();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话