HDU 5371 Hotaru's problem(Manacher)

8 篇文章 0 订阅

Description
定义一个子串,子串由三部分组成,其中第一部分和第三部分相同,第一部分和第二部分对称。给出一个n个数的序列,问序列中最长的符合要求的子串的长度
Input
第一行一整数T表示用例组数,每组用例首先输入一整数n表述序列长度,之后n个整数ai表示该序列(T<=20,n<=100000,0<=ai<=10^9)
Output
对于每组用例,输出序列中最长的符合要求的子串的长度
Sample Input
1
10
2 3 4 4 3 2 2 3 4 4
Sample Output
Case #1: 9
Solution
题目中定义的所谓子串其实就是两个等长回文串且第一个回文串后半部分和第二个回文串前半部分重叠,首先对原序列做一遍Manacher得到以每个字符为中心的回文串的最长长度,之后枚举第一个回文串的中心i,那么第二个回文串的中心j最远为i+ma[i]-1,只要ma[j]>=j-i+1,说明以i,j为中心的这两个回文串组合起来就是符合条件的子串,故在枚举的过程中更新最优解即可
Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 111111 
int ss[2*maxn],ma[2*maxn];
void Manacher(int *s,int len)
{
    int l=0;
    ss[l++]=-2;
    ss[l++]=-1;
    for(int i=0;i<len;i++)
    {   
        ss[l++]=s[i];
        ss[l++]=-1;
    }
    ss[l]=0;
    int mx=0,id=0;
    for(int i=0;i<l;i++)
    {
        ma[i]=mx>i?min(ma[2*id-i],mx-i):1;
        while(ss[i+ma[i]]==ss[i-ma[i]])ma[i]++;
        if(i+ma[i]>mx)
        {
            mx=i+ma[i];
            id=i;
        }
    }
}
int T,n,a[maxn];
int main()
{
    scanf("%d",&T);
    for(int Case=1;Case<=T;Case++)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        Manacher(a,n);
        int ans=0;
        for(int i=1;i<2*n+2;i+=2)
            for(int j=i+ma[i]-1;j-i>ans;j-=2)
                if(j-i+1<=ma[j])
                {
                    ans=max(ans,j-i+1);
                    break;
                }
        printf("Case #%d: %d\n",Case,ans/2*3);
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值