题意感觉有点难懂。但就是问你,给你一个数字串,然后问有没有相同子串(不能重合且长度大于五),或者不用相同的,全部加上一个或减去一个数之后相等的就好。
先是二分长度,然后通过height数组来判断是否可行
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include<string>
using namespace std;
const int maxn =4e4+10;
int n;
struct Suffix
{
int s[maxn];
int SA[maxn],ranked[maxn],height[maxn];
int x[maxn],y[maxn],buc[maxn],len,m;
void init(int *str)
{
//len=strlen(str);
len=n;
for(int i=0;i<len;i++) s[i]=(int)str[i];
m=200;//
}
void build()
{
for (int i = 0; i < m; i++) buc[i] = 0; // buc 是一个桶
for (int i = 0; i < len; i++) buc[x[i] = s[i]]++;
for (int i = 1; i < m; i++)
buc[i] += buc[i - 1];
for (int i = len - 1; i >= 0; i--)
SA[--buc[x[i]]] = i;
for (int k = 1; k <= len; k <<= 1) { // k 倍增
int p = 0;
//对第二关键字排序,y[i]:第i大的第二关键字是谁
// 后缀 len - k 及之后的所有后缀第二关键字最小。为0
for (int i = len - 1; i >= len - k; i--)
y[p++] = i;
for (int i = 0; i < len; i++)
if (SA[i] >= k)
y[p++] = SA[i] - k;
//总体来排个序,求出SA
for (int i = 0; i < m; i++) buc[i] = 0;
for (int i = 0; i < len; i++)
buc[x[y[i]]]++;
for (int i = 1; i < m; i++)
buc[i] += buc[i - 1];
for (int i = len - 1; i >= 0; i--)
SA[--buc[x[y[i]]]] = y[i];
swap(x, y);
p = 1; x[SA[0]] = 0;
// 重新计算每个一元的名次。则x数组里存的是总体的顺序
for (int i = 1; i < len; i++) {
if (y[SA[i - 1]] == y[SA[i]] && y[SA[i - 1] + k] == y[SA[i] + k])
x[SA[i]] = p - 1;
else x[SA[i]] = p++;
}
if (p >= len) break; // 每个后缀的名次已经完全不同,不需要继续倍增
m = p; // 更新名次的最大值。
}
}
void LCP()
{
for(int i=0;i<len;i++)
ranked[SA[i]]=i;
int k=0;
for(int i=0;i<len;i++)
{
if(ranked[i]==0) {height[0]=0;continue;}
if(k) k--;
int j=SA[ranked[i]-1];
while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++;
height[ranked[i]]=k;
}
}
/* int LCS(char *s1)
{
int l=strlen(s1);
s1[l]=' ';
scanf("%s",s1+l+1);
init(s1);
build();
LCP();
int ans=0;
for(int i=1;i<len;i++)
if((SA[i-1]<l&&SA[i]>l)||(SA[i-1]>l&&SA[i]<l))
ans=max(ans,height[i]);
return ans;
}*/
};
Suffix a;
int ok(int mid)
{
int i=1;
while(1){
for(;i<n;i++)
if(a.height[i]>=mid)
break;
if(i>=n) break;
int minn=a.SA[i-1];
int maxx=a.SA[i-1];
while(i<n&&a.height[i]>=mid)
{
minn=min(a.SA[i],minn);
maxx=max(a.SA[i],maxx);
i++;
}
if(maxx-minn>=mid) return 1;
}
return 0;
}
int num[maxn];
int str[maxn];
int main()
{
while(scanf("%d",&n)!=EOF&&n)
{
memset(str,0,sizeof(str));
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
if(n<10) printf("0\n");
else
{
for(int i=1;i<n;i++)
str[i-1]=num[i]-num[i-1]+100;
n--;
// str[n-1]=0;
a.init(str);
a.build();
a.LCP();
int l=4,r=n/2,res=0;
while(l<=r)
{
int mid=l+(r-l)/2;
if(ok(mid)){
res=mid;
l=mid+1;
}
else r=mid-1;
}
if(res>=4)
printf("%d\n",res+1);
else printf("0\n");
}
}
return 0;
}