HDU 4513 吉哥系列故事——完美队形II( Manacher变形 )


**链接:****传送门 **

思路:**根据完美队形的定义,可以得知,完美队形实质上是 回文串 + 序列出现峰,因为是在回文串中再次增加了一个要求,所以可以对 Manacher 进行改造,改造的部分应该为暴力匹配的循环 for( ; str[ i + p[i] ] == str[ i - p[i] ] ; p[ i ]++); ,根据 Manacher 的原理可以得知,如果判断到“间隔符”,直接忽略掉即可,因为它并不影响到“峰值”,对于非间隔符来说,需要判断它与前一个间隔符是否具有序列不增的性质,即可以将 Manacher 的暴力匹配部分改造为 for(😭 str[i-p[i]] == str[i+p[i]] ) && ( ( str[i+p[i]] == -2 ) || ( str[i+p[i]] <= str[i+p[i]-2] ) ) ; p[i]++);,挺好的一道题!
**


/*************************************************************************
    > File Name: hdu4513.cpp
    > Author:    WArobot 
    > Blog:      http://www.cnblogs.com/WArobot/ 
    > Created Time: 2017年05月19日 星期五 23时21分23秒
 ************************************************************************/

#include<bits/stdc++.h>
using namespace std;

#define cls(x) memset(x,0,sizeof(x))
const int MAX_N = 100000*2 + 1000;
int n , s[MAX_N] , str[MAX_N] , p[MAX_N] , len1 , len2;

void init_Manacher(){
	len1 = n;
	str[0] = -1;
	str[1] = -2;
	for(int i = 0 ; i < len1 ; i++){
		str[i*2+2] = s[i];	str[i*2+3] = -2;
	}
	len2 = len1*2 + 2;
	str[len2] = -3;
}

int Manacher(){
	int id , mx = 0;
	for(int i = 1 ; i < len2 ; i++){
		if( mx > i )	p[i] = min( p[2*id-i] , mx - i );
		else			p[i] = 1;
		// 需要对Manacher改造一下,使之能共拥有使序列出现峰值的这个特点
		for(;( str[i-p[i]] == str[i+p[i]] ) && ( ( str[i+p[i]] == -2 ) || ( str[i+p[i]] <= str[i+p[i]-2] ) ) ; p[i]++);
		if( i + p[i] > mx )		mx = i + p[i] , id = i;
	}
	int ret = 0;
	for(int i = 1 ; i < len2 ; i++)	ret = max( ret , p[i] );
	return ret - 1;
}

int main(){
	int t;	
	scanf("%d",&t);
	while(t--){
		cls(s); cls(str); cls(p);
		scanf("%d",&n);
		for(int i = 0 ; i < n ; i++)	scanf("%d",&s[i]);
		init_Manacher();
		int ans = Manacher();
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2017-05-21 23:11  ojnQ  阅读(160)  评论(0编辑  收藏  举报