题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371
1 10 2 3 4 4 3 2 2 3 4 4
Case #1: 9
题意:
给出n个数字,要找其连续的子序列且子序列要满足下面两个条件:
1、所找出的子序列能分为3各部分,第一部分和第二部分是对称的;
2、第一部分和第三部分相同!
求能找出这样的子序列的最大长度!
PS:
manacher算法,利用p[i],加以枚举!
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 200017
int N;
int p[maxn];
int a[maxn];
int b[maxn];
//转换原始串
int n;
void init()
{
int i;
for(i = 0; i < n; i ++)
{
b[2 * i + 1] = -1;
b[2 * i + 2] = a[i];
}
N = 2 * i + 1;
b[0] = -2;
b[N] = b[N + 1] = -1;
}
void manacher()
{
int id;
int maxx = 0;//maxx即为当前计算回文串最右边字符的最大值
int ans = 0;
for(int i = 1; i <= N; i ++)
{
if(maxx > i)
p[i] = min(maxx-i, p[2*id-i]);//在Len[j]和mx-i中取个小
else
p[i] = 1;//如果i>=mx,要从头开始匹配
while(b[i + p[i]] == b[i - p[i]])
++ p[i];
if(i + p[i] > maxx)//若新计算的回文串右端点位置大于maxx,要更新id和maxx的值
{
maxx = i + p[i];
id = i;
}
}
}
int main()
{
int t;
int cas = 0;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
scanf("%d",&a[i]);
}
init();//转换原始串
manacher();
int ans = 1;
// for(int i = 1; i < N; i++)
// {
// printf("%d>>%d\n",b[i],p[i]);
// }
for(int i = 3; i < N; i+=2)
{
for(int j = ans; j <= p[i]; j+=2)
{
if(p[i+j-1] >= j)
{
ans = j;
}
}
}
ans = ans/2*3;
printf("Case #%d: %d\n",++cas,ans);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5371 Hotaru's problem(manacher + 枚举啊)
原文地址:http://blog.csdn.net/u012860063/article/details/47450637