manacher

算法理解

建议阅读算法竞赛上的讲解,阅读之前请先阅读以下文字

算法本质是从一个字符往两边进行扩展,然后找到最长的回文串

\(p[i]\) 表示以 \(s[i]\) 为中心的回文子串的最长回文半径(回文半径包括中心字符)

考虑递推过程,也就是 \(p[1]...p[i-1]\) 已经预处理完了

\(R\) 表示以 \(1...i-1\) 为中心的回文串最大为 \(R-1\),注:\(R\) 表示最大的下一个位置,省去+1/-1

\(C\) 表示 \(R\) 所对应的回文串中心为 \(C\)

好了,接下来开始阅读算法竞赛吧

代码

因为manacher本质上是求奇回文子串,先放一个求奇回文子串的代码

void manacher(){
	int R=0,C=0;
	for(int i=1;i<=n;i++){
		if(i<R)  p[i]=min(p[C*2-i],R-i);
		else  p[i]=1;
		while(s[i+p[i]]==s[i-p[i]])  p[i]++;
		if(p[i]+i>R){
			R=p[i]+i;
			C=i;
		}
	}
}

复杂度证明

考虑 \(R\) 的移动次数最大为 \(n\)

考虑什么时候我们才中心扩展?只有当 \(R\) 要更新的时候我们才会进行中心扩展

最多扩展 \(n\)

posted @ 2025-08-06 18:45  daydreamer_zcxnb  阅读(13)  评论(0)    收藏  举报