若序列ai,ai+1,ai+2,ai+k-1,和aj,aj+1,aj+2,..aj+k-1,满足要求,那ai+1-ai==aj+1-aj,以此类推。所以对原序列进行处理,得到有n-1个元素的序列b,bi代表ai+1-ai的值,那么原问题就转化为了不可重叠最长重复子串。二分结果值k,看是否存在两个长度为k的子串相同,并且不重叠。也就是看是否存在一对后缀,这两个后缀的LCP大于等于k,并且编号差值>=k。把根据height数组分组,得到的每组任意两个后缀的LCP>=k,并且是封闭的,任意一对后缀满足LCP大于等于k的后缀都分别属于这几组,即分了类,然后看每一类中是否至少存在一对。即求出每一组中,sa[i]最大值和最小值的差值,看是否>=k,若存在这样的一个分组,则当前k成立,二分下一个k。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int maxn=20000+10; 6 int num[maxn]; 7 int sa[maxn],t[maxn],t2[maxn],c[maxn],height[maxn],rank[maxn]; 8 int n; 9 void build_sa(int m,int n,int *s) 10 { 11 int i,*x=t,*y=t2; 12 for(i=1;i<m;i++) c[i]=0; 13 for(i=0;i<n;i++) c[x[i]=s[i]]++; 14 for(i=2;i<m;i++) c[i]+=c[i-1]; 15 for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i; 16 for(int k=1;k<=n;k<<=1) 17 { 18 int p=0; 19 for(i=n-k;i<n;i++) y[p++]=i; 20 for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; 21 for(i=1;i<m;i++) c[i]=0; 22 for(i=0;i<n;i++) c[x[y[i]]]++; 23 for(i=2;i<m;i++) c[i]+=c[i-1]; 24 for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; 25 swap(x,y); 26 p=2;x[sa[0]]=1; 27 for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 28 if(p>n) break; 29 m=p; 30 } 31 } 32 void getHeight(int n) 33 { 34 int i,j,k=0; 35 for(i=0;i<n;i++) rank[sa[i]]=i; 36 for(i=0;i<n;i++) 37 { 38 if(k) k--; 39 if(rank[i]) 40 { 41 int j=sa[rank[i]-1]; 42 while(num[i+k]==num[j+k]) k++; 43 height[rank[i]]=k; 44 } 45 } 46 } 47 int bsearch(int n) 48 { 49 int low=3,high=n+1,mid,i,maxv,minv; 50 int flag; 51 while(high>low) 52 { 53 flag=0; 54 mid=low+(high-low)/2; 55 maxv=minv=sa[0]; 56 for(i=1;i<n;i++) 57 { 58 if(height[i]>=mid) 59 { 60 if(sa[i]>maxv) maxv=sa[i]; 61 if(sa[i]<minv) minv=sa[i]; 62 } 63 else 64 { 65 if((maxv-minv)>=mid) 66 { 67 flag=1; 68 break; 69 } 70 maxv=minv=sa[i]; 71 } 72 } 73 if((maxv-minv)>=mid) flag=1; 74 if(flag) low=mid+1; 75 else high=mid; 76 } 77 return (low-1)>3?low:0; 78 } 79 int main() 80 { 81 //freopen("1.txt","r",stdin); 82 while(scanf("%d",&n)&&n) 83 { 84 int i,tem,v; 85 scanf("%d",&tem); 86 for(i=0;i<n-1;i++) 87 { 88 scanf("%d",&v); 89 num[i]=v-tem+88; 90 tem=v; 91 } 92 build_sa(88+88,n-1,num); 93 getHeight(n-1); 94 int ans=bsearch(n-1); 95 printf("%d\n",ans); 96 } 97 return 0; 98 }