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;
}
如要转载请注明转载出处:http://www.cnblogs.com/WArobot