大意:给你一个字符串,求长度超过4、出现2次以上的最长串的长度
首先取相邻的差作为字符串
对这个串建立后缀数组之后
我们二分枚举这个最长串的长度
把所有相邻的大于化作一组
取其中的最大最小值的差
如果存在一组内的差大于,返回,反之
代码:
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
inline int read(){
char ch=getchar();
int res=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
}
const int N=20005;
const int inf=100000000;
int n,m,rk[N],sa[N],a[N],p[N],sa2[N],cnt[N],ht[N];
inline void bucket_sort(){
for(int i=1;i<=m;i++)cnt[i]=0;
for(int i=1;i<=n;i++)++cnt[rk[sa2[i]]];
for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
for(int i=n;i>0;i--)sa[cnt[rk[sa2[i]]]--]=sa2[i];
}
inline void init(){
for(int i=1;i<=n;i++)rk[i]=a[i],sa2[i]=i;
bucket_sort();
for(int i=1,pos=0;i<=n&&pos<n;i<<=1){
pos=0;
for(int j=n-i+1;j<=n;j++)sa2[++pos]=j;
for(int j=1;j<=n;j++)if(sa[j]>i)sa2[++pos]=sa[j]-i;
bucket_sort();
swap(rk,sa2);
rk[sa[1]]=1,pos=1;
for(int j=2;j<=n;j++)rk[sa[j]]=((sa2[sa[j]]==sa2[sa[j-1]])&&(sa2[sa[j]+i]==sa2[sa[j-1]+i])?pos:++pos);
m=pos;
}
for(int i=1;i<=n;i++)rk[sa[i]]=i;
for(int i=1,k=0,j;i<=n;ht[rk[i++]]=k){
for(k?k--:0,j=sa[rk[i]-1];a[i+k]==a[j+k];k++);
}
}
inline bool check(int k){
int minn=inf,maxn=-inf;
for(int i=1;i<=n;i++){
if(ht[i]<k){maxn=-inf,minn=inf;continue;}
maxn=max(maxn,max(sa[i],sa[i-1])),minn=min(minn,min(sa[i],sa[i-1]));
if(maxn-minn>k)return true;
}
return false;
}
int main(){
n=read();
while(n){
for(int i=1;i<=n;i++)p[i]=read();
--n,m=176;
for(int i=1;i<=n;i++)a[i]=p[i+1]-p[i]+88;
init();
int l=4,r=n,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))l=mid+1,ans=mid;
else r=mid-1;
}
if(!ans)ans=-1;
ans++;
cout<<ans<<'
';
n=read();
}
}