HDU 5371 Hotaru's problem(manacher + 枚举啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371


Problem Description
Hotaru Ichijou recently is addicated to math problems. Now she is playing with N-sequence.
Let's define N-sequence, which is composed with three parts and satisfied with the following condition:
1. the first part is the same as the thrid part,
2. the first part and the second part are symmetrical.
for example, the sequence 2,3,4,4,3,2,2,3,4 is a N-sequence, which the first part 2,3,4 is the same as the thrid part 2,3,4, the first part 2,3,4 and the second part 4,3,2 are symmetrical.

Give you n positive intergers, your task is to find the largest continuous sub-sequence, which is N-sequence.
 

Input
There are multiple test cases. The first line of input contains an integer T(T<=20), indicating the number of test cases. 

For each test case:

the first line of input contains a positive integer N(1<=N<=100000), the length of a given sequence

the second line includes N non-negative integers ,each interger is no larger than  109  , descripting a sequence.
 

Output
Each case contains only one line. Each line should start with “Case #i: ”,with i implying the case number, followed by a integer, the largest length of N-sequence.

We guarantee that the sum of all answers is less than 800000.
 

Sample Input
   
   
   
   
1 10 2 3 4 4 3 2 2 3 4 4
 

Sample Output
   
   
   
   
Case #1: 9
 

Source
2015 Multi-University Training Contest 7

题意:

给出n个数字,要找其连续的子序列且子序列要满足下面两个条件:

1、所找出的子序列能分为3各部分,第一部分和第二部分是对称的;

2、第一部分和第三部分相同!

求能找出这样的子序列的最大长度!

PS:

manacher算法,利用p[i],加以枚举!

HDU 5371 Hotaru's problem(manacher + 枚举啊)_第1张图片

代码如下:

#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,回文,Manacher)