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;
}