manacher
manacher可以在(O(n))的时间内求解一个字符串的最长回文子串长度
朴素的做法:
枚举区间左右端点(l),(r),判断([l,r])是否回文,时间复杂度(O(n^3))
优化:
枚举回文中心,分别左右扩展,时间复杂度(O(n^2))
再优化
利用了回文的左右两边相等的性质
code
char str[maxn*2];
int p[maxn*2]; //回文半径数组
int init(char *s) //str数组初始化
{
int len = strlen(s);
int k = 0; //str数组的长度,最后会等于len*2+2
str[k++] = '@'; //开头加个特殊字符
for(int i = 0; i < len; i++)
{
str[k++] = '#';
str[k++] = s[i];
}
str[k++] = '#';
str[k] = 0; //末尾也要不一样,给什么都行
return k;
}
int manacher(char *s)
{
int len = init(s); //str的数组长度
int mx = 0,id = 0; //以id为中心可以扩展到的最右边界mx
int ans = 0; //回文长度
for(int i = 0; i < len; i++)
{
if(mx > i) p[i] = min(mx-i,p[2*id-i]); //如果i小于mx
else p[i] = 1;
while(str[i + p[i]] == str[i-p[i]]) p[i]++; //以i为中心扩展
if(p[i]+i > mx) //更新mx
{
mx = p[i] + i;
id = i;
ans = max(ans,p[i]);
}
}
return ans-1;
}