hdu5371回文串应用

http://acm.hdu.edu.cn/showproblem.php?pid=5371

题意,给出一个串,求最长的子串满足:可以分为等长三段,第一段和第三段相同,第一段和第二段构成回文
直接枚举。
一开始数组开了80010一直tle。。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include 26lt;algorithm>
using namespace std;

const int maxn=100010;
int str[maxn],tmp[maxn<<1];
int len1[maxn<<1];
int init(int *st,int n)
{
    int len=n;
    tmp[0]=-2;
    for(int i=1;i<=2*len;i+=2)
    {
        tmp[i]=-1;
        tmp[i+1]=st[i/2];
    }
    tmp[2*len+1]=-1;
    tmp[2*len+2]=-2;
    tmp[2*len+3]=-3;
    return 2*len+1;
}
int manacher(int *st,int len)
{
    int p=0,ans=0,po=0;
    for(int i=1;i<=len;i++)
    {
        if(p>i) len1[i]=min(p-i,len1[2*po-i]);
        else len1[i]=1;
        while(st[i-len1[i]]==st[i+len1[i]]) len1[i]++;
        if(len1[i]+i>p)
        {
            p=len1[i]+i;
            po=i;
        }
        ans=max(ans,len1[i]);
    }
    return ans-1;
}
int main()
{
    int T,n,cnt=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        scanf("%d",&str[i]);
        int len2=init(str,n);
        int max1=manacher(tmp,len2);
        int ans=0;
        for(int i=1;i<=n*2+1;i+=2)
        {
            for(int j=i+len1[i]-1;j-i>ans;j-=2)//这里不要忘了减一
            {
                if(j-i+1<=len1[j])
                {
                    ans=max(ans,j-i);
                    break;
                }
            }
        }
        printf("Case #%d: %d\n",cnt++,ans/2*3);
    }
    return 0;
}

你可能感兴趣的:(hdu5371回文串应用)