【模板】manacher

原文

我们在原字符串中间添加 # 使得 manacher 可以同时处理奇偶回文

我们对于每一个 i ,若其未超出最大匹配到的范围,则使其按照区间内对称点对称,并按照其对称点的回文长度以及当前 i 到区间右端点取最小值更新当前 i 的回文长度。否则归为 1 。之后朴素算法更新答案,由于中间的那一个字符(包括 #)的对称点是其自身,所以更新后长度要减一。最后如果得到更远的回文范围我们就对范围进行更新。

#include<bits/stdc++.h>
using namespace std;
char a[11000010],s[22000210]; 
int len;
void change()
{
	s[0]=s[1]='#';
	for(int i=0;i<len;++i)
	{
		s[(i<<1)+2]=a[i];
		s[(i<<1)+3]='#';
	}
	len=(len<<1)+2;
	s[len]=0;
}
int dr[22000210];
int ans=0;
void manacher()
{
	int mid=0,maxr=0;
	for(int i=0;i<len;++i)
	{
		if(i<maxr) dr[i]=min(dr[(mid<<1)-i],maxr-i);
		else dr[i]=1;
		while(i-dr[i]>=0&&i+dr[i]<len&&s[i-dr[i]]==s[i+dr[i]]) ++dr[i];
		--dr[i];
		if(i+dr[i]>maxr) 
		{
			maxr=i+dr[i];
			mid=i;
		}
	}
}
int main()
{
	scanf("%s",a);
	len=strlen(a);
	change();
	manacher();
	for(int i=0;i<len;++i) ans=max(ans,dr[i]);
	printf("%d",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值