manacher 模板

求最长回文子序列的 O(n)做法
讲解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
const int MAXN=11000117;
char s[MAXN],snew[MAXN*2+5];
int p[MAXN*2+5];
int init(){
	int len=strlen(s);
	snew[0]='&';snew[1]='#';
	int j=2;
	for(int i=0;i<len;i++){
		snew[j++]=s[i];
		snew[j++]='#';
	}
	snew[j]='\0';
	return j;
}
int manacher(){
	int ans=0;
	int len=init();
	int id=0,mx=0;
	for(int i=1;i<len;i++){
		if(i<mx) p[i]=min(p[id*2-i],mx-i);
		else p[i]=1;
		while(snew[i-p[i]]==snew[i+p[i]]) p[i]++;//注意这里的循环写在if外面,因为如果p[i]+i==mx,还可以向外扩展
		if(i+p[i]>mx){
			mx=i+p[i];
			id=i;
		}
		ans=max(ans,p[i]-1);
	}
	return ans;
}
int main(){
	freopen("in.txt","r",stdin);
	scanf("%s",s);
	printf("%d",manacher());
	fclose(stdin);
	return 0;
}
posted @ 2017-12-04 19:19  Mr_Wolfram  阅读(209)  评论(1编辑  收藏  举报