算法专题
前言
所讲例题 |
---|
洛谷 3805【模板】manacher算法 |
JZOJ 2682 洛谷 4555 最长双回文串 |
JZOJ 1950 洛谷 1659 拉拉队排练 |
洛谷 3805【模板】manacher算法
题目
找到一个字符串中的最长回文子串
分析
首先字符串的长度为 n ≤ 11000000 n\leq 11000000 n≤11000000,显然只能用 O ( n ) O(n) O(n)的时间完成这道题目,首先朴素的方法就是 O ( n 2 ) O(n^2) O(n2),也就是枚举中间点向外扩展,但是这样的坏处在哪里呢,就是这样扩展很有可能找不到最优解而浪费了时间,那应该怎么做呢?
那就可以引进一种神奇的算法,manacher
那么这是什么神奇的东西呢,首先对于长度奇偶性可以在字符串中间填充分隔符,这样字符串就一定是奇数,为了避免越界,还要在开头加一个分隔符。
那要记录三样东西,首先是 p [ i ] p[i] p[i]表示中点为 i i i时的最长回文串的半径,然后那么显而易见答案就是 m a x { p [ i ] − 1 } max\{p[i]-1\} max{
p[i]−1},那问题是答案怎么算,这是一个大问题
再首先,我们要记录两个东西, m i d mid mid表示当前找到的最长回文串的中点, m x mx mx表示该回文串的右边界。
首先对于每一个 i i i,若 i < m x i<mx i<mx说明还是有希望的,否则就只能像纯模拟一样 p [ i ] = 1 p[i]=1 p[i]=1
当然不管怎么样还是得加上这句话 w h i l e ( s [ i − p [ i ] ] = = s [ i + p [ i ] ] ) + + p [ i ] ; while (s[i-p[i]]==s[i+p[i]]) ++p[i]; while(s[i−p[i]]==s[i+p[i]])++p[i];
那 i f ( m x < i + p [ i ] ) m x = i + p [ i ] , m i d = i ; if (mx<i+p[i]) mx=i+p[i],mid=i; if(mx<i+p[i])mx=i+p[i],mid=i;是为什么,显然可知是更新最长回文子串
但问题是 m a n a c h e r manacher manacher如何优化呢,那就是 i < m x i<mx i<mx的情况了
那么首先设 j = 2 ∗ i − m i d j=2*i-mid