本题需要对s数组做一下调整,然后求数组s中最长不重叠重复子串
#include<cstdio>
#include<cstring>
const int maxn=20005;
int s[maxn],rank[maxn],height[maxn],sa[maxn],wa[maxn],wb[maxn],wv[maxn],ws[maxn],n;
int mind[maxn][15],maxd[maxn][15];
void adjust_s(int *s,int &n)
{
int i=0,minv=200;
for(i=0;i<n-1;i++)
{
s[i]=s[i+1]-s[i];
minv=minv>s[i]?s[i]:minv;
}
for(i=0;i<n-1;i++)
{
s[i]-=minv;
}
n--;
/*for(i=0;i<n;i++)
printf("%d ",s[i]);
printf("\n");*/
}
int cmp(int *r,int a,int b,int l)
{
if(r[a]!=r[b]) return 1;
if(a+l>=n && b+l>=n) return 0;
if(a+l<n && b+l<n && r[a+l]==r[b+l]) return 0;
return 1;
}
void build_sa(int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[x[i]=s[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
for(j=1,p=1;p<n;j<<=1,m=p)
{
p=0;
for(i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[wv[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
t=x;x=y;y=t;p=1;x[sa[0]]=0;
for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)==0?p-1:p++;
}
/*for(i=0;i<n;i++)
printf("%d ",sa[i]);
printf("\n");*/
}
void get_height()
{
int i,j,k=0;
for(i=0;i<n;i++) rank[sa[i]]=i;
for(i=0;i<n;i++)
{
if(k) k--;
j=rank[i]-1;
if(j==-1)
{
height[0]=0;
continue;
}
j=sa[j];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
/*for(i=0;i<n;i++)
printf("%d ",rank[i]);
printf("\n");
for(i=0;i<n;i++)
printf("%d ",height[i]);
printf("\n");*/
}
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a>b?b:a;
}
void RMQ_INIT(int *r,int n)
{
int i,j;
for(i=0;i<n;i++) mind[i][0]=maxd[i][0]=r[i];
for(j=1;(1<<j)<=n;j++)
{
for(i=0;i+(1<<j)-1<n;i++)
{
mind[i][j]=min(mind[i][j-1], mind[i+(1<<(j-1))][j-1]);
maxd[i][j]=max(maxd[i][j-1], maxd[i+(1<<(j-1))][j-1]);
}
}
}
int RMQ_QUERY(int l,int r,int flag)
{
int k=0;
while((1<<(k+1))<(r-l+1)) k++;
if(flag)
return max(maxd[l][k], maxd[r-(1<<k)+1][k]);
else
return min(mind[l][k], mind[r-(1<<k)+1][k]);
}
int judge(int k)
{
int i,j,v1,v2,start=1,end=0;
for(i=1;i<n;i++)
{
if(height[i]>=k) end++;
if((height[i]<k || i==n-1) && start<=end)
{
v1=RMQ_QUERY(start-1,end,0);
v2=RMQ_QUERY(start-1,end,1);
if(v2-v1>k)
return 1;
start=i+1;end=i;
}
if((height[i]<k || i==n-1) && start>end)
{
start=i+1;end=i;
}
}
return 0;
}
int main()
{
int i,j,mid,l,r;
while(scanf("%d",&n)!=EOF&&n!=0)
{
for(i=0;i<n;i++)
scanf("%d",&s[i]);
if(n<10)
{
printf("0\n");
continue;
}
adjust_s(s,n);
build_sa(200);
get_height();
RMQ_INIT(sa,n);
l=0;r=n/2;
while(l<=r)
{
mid=(l+r)/2;
if(judge(mid))
l=mid+1;
else
r=mid-1;
}
printf("%d\n",l>=5?l:0);
}
return 0;
}