Manacher 算法 
例题:P3805 【模板】manacher - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 
给出一个只由小写英文字符 a , b , c , … y , z \texttt a,\texttt b,\texttt c,\ldots\texttt y,\texttt z a , b , c , … y , z   组成的字符串 S S S   ,求 S S S   中最长回文串的长度 。
 
Manacher 算法是一种快速找到字符串中所有回文串长度的线性算法。
奇偶回文长度统一处理 
回文串存在两种形式:形如 abba \texttt {abba} abba   的偶数回文串以及形如 abbcbba \texttt {abbcbba} abbcbba   的奇数回文串。
我们令 f i ( 1 ≤ i ≤ ∣ S ∣ ) f_i (1 \le i \le |S|) f i  ( 1 ≤ i ≤ ∣ S ∣ )   表示以第 i i i   个字符串为中心形成的最长 回文串,显然偶数回文串就不好处理了。
我们将每个字符之间用一个无关字符代替,例如 abba ← !a!b!b!a! \texttt{abba} \leftarrow \texttt{!a!b!b!a!} abba ← !a!b!b!a!  。这样处理之后,每个偶回文串的中心就是无关字符了,可用来记录。与此同时,不难发现每个回文串的长度都增加了,设当前为 f i ′ f'_i f i ′   ,原来为 f i f_i f i   ,不难发现:
⌊ f i ′ 2 ⌋ = f i \left \lfloor \frac{f'_i}{2}  \right \rfloor = f_i
 ⌊ 2 f i ′   ⌋ = f i  
我们只需要记录当前点 i i i   到达其中一端的距离便是原来的回文串长度 f i f_i f i   ,而这在 Manacher 算法里更加方便。
实现过程 
对于一个穿 S S S  ,假设我们应处理完了前 i − 1 i - 1 i − 1   个,并且第 i − 1 i - 1 i − 1   个回文串的左右边界为 l , r l, r l , r  。
对于当前的新下标 i,有如下几种情况:
i > r i \gt r i > r  ,很显然,前面处理的都没有用,暴力循环记录即可。 
i < r i \lt r i < r  ,这说明 f i f_i f i    有一部分是已经处理过的,而由于回文的对称性质,子串 S [ i , r ] S[i, r] S [ i , r ]   和子串 S [ l , l + r − i ] S[l, l + r - i] S [ l , l + r − i ]   互为逆字符串(当然前提是 f l + r − i ≤ i − l + 1 f_{l + r - i} \le i - l + 1 f l + r − i  ≤ i − l + 1  )。这又可以分为两种情况讨论:
f l + r − i ≤ i − l + 1 f_{l + r - i} \le i - l + 1 f l + r − i  ≤ i − l + 1  :此时说明 S [ l , l + r − i ] S[l, l + r - i] S [ l , l + r − i ]   与 S [ i , r ] S[i, r] S [ i , r ]   可以匹配,但是 r r r   右侧无法得知,暴力循环从 r r r   继续遍历即可。 
f l + r − i > l − i + 1 f_{l + r - i} \gt l - i + 1 f l + r − i  > l − i + 1  :此时说明 S [ l , r ] S[l, r] S [ l , r ]   是回文串,S [ l + r − i − f l + r − i , l + r − i + f l + r − i ] S[l + r - i - f_{l + r - i}, l + r - i + f_{l + r - i}] S [ l + r − i − f l + r − i  , l + r − i + f l + r − i  ]   也属于回文串,f_i 此时不能再向右侧扩展,故 f i ← f l + r − 1 f_i \leftarrow f_{l + r - 1} f i  ← f l + r − 1   。 
 
 
 
时间复杂度分析 
由上述过程可知,每一次循环都要判断右边界 r r r  ,并且每一次循环都会使得 r ← r + 1 r \leftarrow r + 1 r ← r + 1  ,由于 r r r   只会增加到 ∣ S ∣ |S| ∣ S ∣  ,因此时间复杂度为 O ( ∣ S ∣ ) O(|S|) O ( ∣ S ∣ )  ,即线性复杂度。
代码实现 
预处理:
1 2 3 4 s[0 ] = '#' ;     for  (int  i = 0 ; i < str.size (); i ++)         s[++ idx] = str[i], s[++ idx] = '#' ; s[len = idx] = '#' ; 
 
核心代码:
1 2 3 4 5 6 7 for  (int  i = 0 , l = 0 , r = -1 ; i <= len; i ++)    {         int  k = (i > r) ? 1  : min (r - i + 1 , ans[l + r - i]);         while  (i - k >= 0  && i + k <= len && s[i - k] == s[i + k]) k ++;         ans[i] = k --;             if  (i + k > r) r = i + k, l = i - k;         } 
 
Reference 
Manacher - OI Wiki (oi-wiki.org) 
P3805 【模板】manacher - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)