当前位置:网站首页>Manacher(求解最长回文子串)
Manacher(求解最长回文子串)
2022-08-04 15:11:00 【AC__dream】
说这个算法之前先来说一下暴力中心扩展算法求解最长回文子串问题,就是我们枚举每一个中心点,然后依次暴力向外扩展直到遇到两端字符不相同时停止扩展,就得到了以当前字符为中心时的最长回文子串,最长回文子串为奇数和偶数的情况分别考虑一下即可。我们可以把一个字符串添加一些字符,使其偶回文子串可以变成奇回文子串,就在字符串每两个相邻字符之间添加一个‘#’,然后在字符串开头和结尾再分别添加一个字符即可。比如字符串cbbc,添加后得到#c#b#b#c#,这样原来偶回文串的中心就变为以#为中心的奇回文串了,这样我们就可以只研究最大奇回文子串的求法了。
Manacher算法就是对暴力中心扩展算法进行了优化,充分利用了回文串对称的性质来进行优化,最终复杂度是O(n)
记p[i]表示第i个字符到可以扩展到的最右边的字符的距离,包含第i个字符。
id是回文子串中右边界最大的回文子串的中心,mx是以id为中心的最大回文子串的右边界的下一个字符。
由于我们是从前往后遍历的,假设当前遍历到了第i个字符,那么对于所有的p[1~i-1]都是已知的。
如果i<mx,那么对应着下图的情况:
那么我们可以找出来i关于id的对称点j,也就是2*id-i,由对称性可以知道如果j的最大回文子串不超过以id为中心的最大回文子串,那么i的回文子串就与j相同,记i到mx的距离为mx-i,如果j的最大回文子串不在以id为中心的最大回文子串中,那么i的最大回文子串的右边界就一定是mx-1,因为因为mx是以id为中心扩展不到的第一个位置,说明mx所在位置的字符与mx关于id对称得到的位置的字符是不同的,而由于j的最大回文子串包含mx关于id对称得到的位置的字符,所以i的最大回文子串就不会包含mx位置所对应的字符,那么总的来说,p[i]=min(p[j],mx-i)
如果i>=mx,也就是说i不在之前所得到的所有回文子串中,所以只能设其p数组为1
然后我们只能暴力扩展求得其p数组,由于mx是递增的,最大扩展n次,所以总的复杂度就是O(n)
最后注意一点,为了使得我们不用处理边界问题,我们可以令两个边界是我们没用过的字符。
下面给出一道洛谷模板题链接:【模板】manacher 算法 - 洛谷
细节见代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=3e7+10;
char s[N];
int p[N],mx,id;
int main()
{
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=n;i>=0;i--)
{
s[2*i]=s[i];
s[2*i+1]='#';
}
s[0]='$';
for(int i=1;i<=2*n+1;i++)
{
if(i<mx) p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while(s[i-p[i]]==s[i+p[i]]) p[i]++;
if(i+p[i]>mx)
{
id=i;
mx=i+p[i];
}
}
int ans=0;
for(int i=1;i<=2*n+1;i++) ans=max(ans,p[i]-1);
printf("%d",ans);
return 0;
}
边栏推荐
猜你喜欢
什么,你告诉我?作用域也分种类?
小程序|炎炎夏日、清爽一夏、头像大换装
leetcode: 259. Smaller sum of three numbers
Technology sharing | Description of the electronic fence function in the integrated dispatching system
微软表示将向内部网络安全专家共享数据 为企业提供更安全保护
Byte、Short、Integer、Long内部缓存类的对比与源码分析
Redis 高可用
leetcode:253. 至少需要多少间会议室
Bluetooth Technology|In the first half of the year, 1.3 million charging piles were added nationwide, and Bluetooth charging piles will become the mainstream of the market
Flutter 运动鞋商铺小demo
随机推荐
2022杭电多校4
How to fall in love with a programmer
如何优雅的消除系统重复代码?
Nuget 通过 dotnet 命令行发布
附加:自定义注解(参数校验注解);(写的不好,别看…)
Redis-哨兵模式
Find My Technology | Prevent your pet from getting lost, Apple Find My technology can help you
游戏网络 UDP+FEC+KCP
FRED应用:毛细管电泳系统
leetcode: 250. Count subtrees of equal value
Sublime Text 好用的插件
Why, when you added a unique index or create duplicate data?
Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World。
基于数据库实现分布式锁
1403. 非递增顺序的最小子序列
IP第十八天笔记
技术分享| 小程序实现音视频通话
MVCC实现过程
洛谷题解P4326 求圆的面积
Next -20- 使用自定义样式 (custom style)