HDU 5371 Hotaru's problem(manacher算法)

Hotaru's problem

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


 

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

 

为了方便找模板。。写个题解。。

题意:给你一个具有n(n<=1e5)个元素的整数序列,问你是否存在这样一个子序列,该子序列从左到右分为长度相等的三部分,第一部分与第三部分相同,第二部分与第一部分对称(例如 234 432 234 ),要求给出形如所述的最长连续子序列。

思路:易知234432 和432234都是回文子序列,即由前一个子序列的后半部分和后一个前半部分相同的两个回文子序列组成。

因此先用马拉车算法O(n)求出每个以 i 为中心和以 i和i+1 为中心的最长回文串长度。然后本题满足条件的只有i和i+1为中心的最长回文串长度,在纸上画画发现x>max&&p[i+x]>=x时符合条件(x=p[i]-1),否则看 --x,直到满足条件或者小于max。最后不要忘了/2*3。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+10;
const int inf=0x3f3f3f3f;
int n,m,k;
int p[maxn],s[maxn],ans;
void manacher()
{
    int id=0,maxlen=0;
    for(int i=n;i>=0;i--)
    {
        s[i*2+2]=s[i];
        s[i*2+1]=-1;
    }
    s[0]=-2;
    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(maxlen<p[i]) maxlen=p[i];
    }
    //printf("%d\n",maxlen);
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        memset(p,0,sizeof(p));
        for(int i=0;i<n;i++) scanf("%d",&s[i]);
        manacher();ans=0;
        /*for(int i=3;i<2*n+1;i+=2)
        printf(" %d",p[i]-1);*/
        for(int i=3;i<2*n;i+=2)
        if(p[i]-1>ans){
            int t=p[i]-1;
            while(t>ans&&p[i+t]<t) t--;
            ans=max(ans,t);
        }
        printf("Case #%d: %d\n",cas++,ans/2*3);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值