Manacher算法
Manacher
一个O(n)求回文串的算法。
算法流程
1、消除奇偶差别. 在字符之间插入’#‘或’$‘等一类不属于原字符串的字符。
2、R[i]. 对每个位置求出R[i],即以当前位置为对称中心,对称半径最大为多少。
求R[i]
从前往后扫,维护目前所有回文串的最右端(即能遍历到的最右端)Right,以及取到Right时的对称中心mid。
1、若当前位置i不在Right左边,将其R[i]设为1。若当前位置i在Right左边,将R[i]设为,\(min(R[mid * 2 - i] , R - i)\)
2、以当前的R[i]为基础,判断\(s[i-R[i]] == s[i+R[i]]\) 不断增大R[i]。
3、更新mid,R[i].
代码
给一个长度在1200以内的由小写字母组成的字符串,求最长回文串的长度
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int R[2420];
char s[1210] , c[2420];
int main()
{
while(scanf("%s" , s+1) != EOF)
{
int n = 0 , Right = 0 , mid = 0 , ans = 0;
for(int i = 1 ; s[i] ; ++i)
{
c[++n] = '#'; c[++n] = s[i];
}
c[++n] = '$';
for(int i = 1 ; i <= n ; ++i)
{
if(i < Right) R[i] = min(Right - i , R[2 * mid - i]); else R[i] = 0;
while(c[i + R[i] + 1] == c[i - R[i] - 1] && (i + R[i] + 1 <= n) && (i - R[i] - 1 >= 1)) R[i]++;
if(i + R[i] > Right) Right = i + R[i] , mid = i;
}
for(int i = 1 ; i <= n ; ++i) ans = max(ans , R[i]);
printf("%d\n" , ans);
}
return 0;
}

浙公网安备 33010602011771号