manacher算法

功能:求最长回文串

1、统计奇偶
方法:在各个字符间插入特殊字符,如’#’。为省略边界判断常在开始再加入’\(’。 如:ababac变为\)#a#b#a#b#a#c#

这样所有的回文串的长度都变为奇数。而原回文串的长度为现在回文串半径减1。
如: $#a#b#a#b#a#c#
半径长度 11214161412121
回文串长度 00103050301010
如果mx>i,则有以下两种情况
情况一:i+len[j]-1<mx,则len[i]=len[j]

情况二:i+len[j]-1>=mx,则len[i]=mx-i+1,然后依次枚举判断S[mx+1…(增大)]==s[2*i-mx-1...(减小)]

如果mx<=i,则将则len[i]=1,然后依次枚举判断
S[i+1…(增大)]==s[i-1...(减小)]
P3805 manacher算法

#include <cstdio>
#include <iostream>
#include <cstring>
#define orz cout << "AK IOI"

using namespace std;
const int N = 1e7 + 1e6 + 5;

char s[N], str[N << 1];
int le, id, mx, len[N << 1], ans = -1;
void getstr()
{
	int k = 0;
	str[k++] = '$';
	for(int i = 0; i < le; i++)
	{
		str[k++] = '#';
		str[k++] = s[i];
	}
	str[k++] = '#';
	le = k;
}
int main()
{
    cin >> s;
    le = strlen(s);
    getstr();
    for(int i = 1; i <= le; i++)
    {
    	if(mx > i) len[i] = min(len[2 * id - i], mx - i);//分别为两种情况
		else len[i] = 1;//第三种情况
		while(str[i + len[i]] == str[i - len[i]])//多余的部分进行比对
		len[i]++;
		if(len[i] + i > mx)
		mx = len[i] + i, id = i; 
	}
    for(int i = 1; i <= le; i++)
    ans = max(ans, len[i]);
    printf("%d", ans - 1);
    return 0;
}
posted @ 2021-01-13 15:58  _程门立雪  阅读(103)  评论(3编辑  收藏  举报