[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=39091399
(优快云好像有bug,不知道为什么存的草稿覆盖了之前的博客>.<,以后再也不存线上草稿了)
昨天学了马拉车(manacher)算法,今天做了一道例题。虽然并不难,但还是写一写博客,即为民服务,又加深自己的理解。
manacher是高效处理回文串的算法,不过因为只限求回文串,所以适用范围就窄了,但是它仍然有用,所以还是要学。
首先是一个小小的处理技巧。因为回文串可能是奇数可能是偶数,偶数的时候就没有中心字符了,没有著脚点可恼火了。所以我们考虑用没有出现过的字符“#”来表示原串的间隔。eg。ababa->#a#b#a#b#a#。为了避免溢出,访问到不存在的点(’\0’=’\0’),我们再在首尾加上没有出现过的不同字符,eg’+’,’-‘。显然,现在对新串的每一个字符找以此字符为中心的字符串即可。
manacher的思想就是从左到右求出以每个位置为中心的最长字符串(由于回文串很明显的包含和对称性质,以同一位置为中心的字符串自然是包含在最长回文串里),利用回文串的对称性质,对每一个位置利用之前的信息来快速得到答案。近似于扫一遍,所以均摊o(n)(之后详细证明)
那么之前的信息是什么呢?我们记向右延伸最远的回文串(有多个的话,选中心点最靠左的),令其右端点为mx,中心点的下标为id。我们需要处理数组pal[i],表示以i为中心的回文串的右端到i的长度。
下面就是怎么实现的问题了。
对于一个位置i,有三种情况
1、i<=mx,我们可以由对称性得出其关于id的对称点的pal[]
此时易得pal[i]=pal[2*id-i];
2、同样的情况,i<=mx,但是其对应点的范围超出了id的范围。