求助manacher板子
  • 板块灌水区
  • 楼主JackHu0117
  • 当前回复12
  • 已保存回复12
  • 发布时间2023/9/30 19:34
  • 上次更新2023/11/2 16:55:41
查看原帖
求助manacher板子
647952
JackHu0117楼主2023/9/30 19:34

link 感觉发题目版都没人会看
66code:
#7#8#14#15TLE

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
char s[11000010<<1],a[11000010];
int r[11000010<<1];//r是s[i]的最大回文半径
int len;
inline void change(){//manacher在每个字符后插入其他字符
	len=strlen(a);
	int cnt=0;s[cnt++]='$';s[cnt++]='#';//开始
	for(int i=0;i<len;++i){
		s[cnt++]=a[i];
		s[cnt++]='#';//在每个字符后插入#
	}
	s[cnt++]='&';//标示结束
	len=cnt;//更新长度
}
inline void manacher(){
	int c=1,r1=0;//当前中心当前访问到的最远右端
	for(int i=1;i<len;++i){//遍历
		if(i>r1){//如果当前遍历点i在c左r右
			//i的镜像点j即c*2-i
			r[i]=min(r[c<<1-i],r[c]+c-i);
			//r[i]再大也不会超过j点的回文即r[c*2-i]
			//也不会超过r即r[c]+c-i
		}else{//如果当前遍历点在r右
			r[i]=1;//因为没有遍历过r外的情况,只能初始化为一
		}
		while(s[i-r[i]]==s[i+r[i]]) ++r[i];//暴力中心扩展
		if(r[i]+i>r1){
			r1=r[i]+i;
			c=i;//更新r
		}
	}
}
int main(){
	scanf("%s",a);
	change();manacher();
	int ans=-1;
	for(int i=0;i<len;i++){
		ans=max(ans,r[i]);
	}
	printf("%d",ans-1);
//	cout<<ans-1<<endl;
	//比如一个回文串是#a#a#a#a#a#
	//这样若以中间的a为中心,其右边有k个a,k+1个#
	//而这个回文串总共的a有k*2+1个,正好是其右边a的个数加上#的个数
	//但是又因为是从1开始计数,hw把本身也算了进来,所以ans-1就是答案
	return 0;
}
2023/9/30 19:34
加载中...