HDU 5371 Hotaru's problem(Manacher 求一序列三部分回文)

来源:互联网 发布:手机 惯性导航算法 编辑:程序博客网 时间:2024/04/25 09:08

Hotaru's problem

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1268    Accepted Submission(s): 448


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
1102 3 4 4 3 2 2 3 4 4
 

Sample Output
Case #1: 9
给你n个数 求一个最长的连续序列 可以分为3部分 ,其中第一部分和第二部分为回文,第二部分和第三部分回文
2 3 4 4 3 2 2 3 4 就是满足的一个序列
用Manacher算法求出Len[i] , Len[i] 表示回文的最右端到 i 的距离
#include <cstdio>#include <algorithm>#include <stdlib.h>#include <cstring>#include <iostream>#include <cmath>#define maxn 100010using namespace std;int a[maxn];int tmp[maxn*2];int Len[maxn*2];int n;int init(int s[]){    tmp[0]=-1;    for(int i=1; i<=2*n; i+=2)    {        tmp[i] = 0;        tmp[i+1] = s[i/2];    }    tmp[2*n+1] =0;    tmp[2*n+2] = -2;    return 2*n+1;}void Manacher(int s[],int len){    int mx=0;    int po=0;    for( int i=1; i<=len; i++)    {        if(mx > i)            Len[i] = min(mx-i , Len[2*po-i]);        else            Len[i] = 1;        while( s[i-Len[i]]== s[i+Len[i]] )        {            Len[i]++;        }        if(Len[i]+i>mx)        {            po=i;            mx=Len[i]+i;        }    }}int main(){    int T;    int ca=1;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        for(int i=0; i<n; i++)            scanf("%d",&a[i]);        int len = init(a);        Manacher(tmp,len);        int ans=1;        for(int i=1; i<len; i+=2)            for(int j=ans; j<=Len[i]; j+=2)        //对于满足要求的一个序列            {                                       //分成三段的两个点为i ,i+j-1 (每一部分长度为j)                if(Len[i]>=j && Len[i+j-1]>=j)     //对于i点 ,它右侧的回文长度大于j(即第二段长度)                    {                              // 所以i+j-1点右侧回文长度也要大于j                          ans=j;                    }            }        ans--;                              //   Manacher算法求出的ans-1位回文长度        printf("Case #%d: ",ca++);          //   此时ans为第一部分 和 第二部分的长度和        printf("%d\n",ans/2*3);    }    return 0;}


 
0 0
原创粉丝点击