马拉车(Manacher)算法

文章目录

前言

马拉车算法在O(n)的情况下求解一个字符串的最长回文子串的长度

思路

首先,我们问了解决问题方便,不用讨论奇偶,在首尾处和原字符串每个相邻两个字符中间插入一个分隔符。

设置一个辅助数组p[i],表示以字符s[i]为中心的最长回文字串的最右字符到s[i]的长度。比如以s[i]为中心的最长回文子串是s[l,r],那么p[i]=r-l+1.

关于p数组的求法:
首先从左到右依次计算len[i],当计算len[i]时,len[j] (0<j<i)已经被计算过了。设mx为之前计算中最长回文子串的右端点的最大值,并且设置取得这个最大值的位置为id.
分两种情况讨论
情况一:当i<mx时,若len[j]<mx-i,则说明以j为中心的回文串一定在以id为中心的回文串内部。以i为中心的回文串的长度与以j为中心的回文串长度相同。 若len[j]>=mx-i,由于对称性,我们知道以i为中心的回文串可能会延伸到p之外,而大于p的地方我们还没有匹配,所以我们要从p+1的位置开始一个一个的匹配,更新mx,id,len[i].
情况二:i>p,一个一个匹配,更新id,mx,len[i].
在这里插入图片描述

参考

代码

const int maxn=1e5+10;
char str[maxn];
char p[maxn<<1];
int l[maxn<<1];
void malache()
{
	int len=strlen(str);
	p[0]='#';p[1]='#';
	for(int i=0;i<len;i++)
	{
		p[(i+1)<<1]=str[i];
		p[(i+1)<<1|1]='#';
	}
	int mx=0,id=0,ans=0;
	for(int i=0;i<2*len+1;i++)
	{
		if(i<mx) l[i]=min(l[2*id-i],mx-i);
		else l[i]=1;
		while(p[i-l[i]]==p[i+l[i]]) l[i]++;
		if(l[i]+i>mx) id=i,mx=i+l[i];
		ans=max(ans,l[i]);
	}
	cout<<ans-1<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值