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\) 次

浙公网安备 33010602011771号