题目地址:HDU 5371
题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列,该子序列分为三部分,第一部分与第三部分相同,第一部分与第二部分对称,如果存在求最长的符合这种条件的序列。
思路:用Manacher算法来处理回文串的长度,记录下以每一个-1(Manacher算法的插入)为中心的最大回文串的长度。然后从最大的开始穷举,只要p[i]-1即能得出以数字为中心的最大回文串的长度,然后找到右边对应的’-1’,判断p[i]是不是大于所穷举的长度,如果当前的满足三段,那么就跳出,继续下一个以数字为中心的回文串。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef __int64 LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-7;
const int Maxn=100005;
int str[Maxn];
int s[Maxn*2];
int p[Maxn*2];
int n;
void Manacher()
{
memset(p,0,sizeof(p));
s[0]=-2;
s[1]=-1;
for (int i=0;i<n;i++) {
s[i*2+2]=str[i];
s[i*2+3]=-1;
}
int MaxL=0,id=0;
for (int i=2; i<2*n+1; i++) {
if (p[id]+id>i)
p[i]=min(p[2*id-i],p[id]+id-i);
else
p[i]=1;
while (s[i-p[i]]==s[i+p[i]])
p[i]++;
if(id+p[id]<i+p[i])
id = i;
if (p[i]>MaxL)
MaxL=p[i];
}
}
int main()
{
int T,i;
int Max;
int ans;
int icase=1;
scanf("%d",&T);
while(T--) {
Max=0;
scanf("%d",&n);
for(i=0; i<n; i++)
scanf("%d",&str[i]);
Manacher();
for(i=3; i<2*n+1;i+=2){
ans=p[i]-1;
while(ans>Max&&p[i+ans]<ans)
ans--;
Max=max(Max,ans);
}
printf("Case #%d: %d\n",icase++,Max/2*3);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5371(2015多校7)-Hotaru's problem(Manacher算法求回文串)
原文地址:http://blog.csdn.net/u013486414/article/details/47446511