Manacher
今天讲的字符串哈希题觉得都很水啊,咋一听到 Manacher 题就懵逼了呢?重学一遍……
简介
给定一个长度为 的字符串 ,找到所有回文子串。
最坏情况下有 个回文串,为了做到线性,我们使用回文半径来表示回文。这样,我们要求的就转化为:对于每个位置 ,求出最长回文半径。
使用字符串哈希可以容易地在 时间内解决,但 Manacher 更为简洁和高效。
实现过程
约定: 表示下标在 之间的子串。
我们只考虑长度为奇数的回文串,可以通过在字符串每个字符间加入无关字符如 #
等来把长度为偶数的串转化为长度为奇数的串。接下来,我们维护 表示以 为重心的回文半径, 为当前找到的覆盖位置最靠右的回文串能覆盖到的最大下标, 表示它的回文中心的下标。
计算过程考虑分类讨论:
- 时,直接暴力一步步向后跳。
- 时,设 为 关于 的对称点,即 。
由于 与 相等且都是回文串,所以 可以直接取 的值。但这个推论成立当且仅当 ,否则 只能取到 ,然后再暴力扩展。
综上,。
只能向右移动,故最多移动 次。其余情况的计算显然是 的。
1 | for(int i=1,r=0,mid=0;i<=n;i++){ |
部分引自 https://oi-wiki.org/string/manacher/
非常感谢这篇博客,讲的很透彻,帮我彻底弄懂了 Manacher。
https://www.luogu.com.cn/article/2fmdma9m
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 headless-piston's Blog!
评论