获得原数列的差分数列,离散化后接在一起,中间用没有出现过的数分隔,于是问题就转化成求这个数列的最长重复子串,且每一段上都至少有一个子串。
求出后缀数组,二分答案即可。
1 #include<bits/stdc++.h> 2 #define R register 3 using namespace std; 4 const int N=1010,M=1000010,oo=2e9; 5 int n,m,tot,s[M],a[M],numpos[M]; 6 int x[M<<1],y[M<<1],sa[M<<1],rank[M],h[M],height[M],cnt[M],bel[M]; 7 int cmp(const int xx,const int yy){return a[xx]<a[yy];} 8 void build(){ 9 for(R int i=1;i<=n;i++) cnt[x[i]]++; 10 for(R int i=2;i<=m;i++) cnt[i]+=cnt[i-1]; 11 for(R int i=n;i;i--) sa[cnt[x[i]]--]=i; 12 for(R int i=1;i<=m;i++) cnt[i]=0; 13 for(R int k=1;k<=n;k<<=1){ 14 int num=0; 15 for(R int i=n;i>n-k;i--) y[++num]=i; 16 for(R int i=1;i<=n;i++) if(sa[i]>k) y[++num]=sa[i]-k; 17 for(R int i=1;i<=n;i++) cnt[x[i]]++; 18 for(R int i=2;i<=m;i++) cnt[i]+=cnt[i-1]; 19 for(R int i=n;i;i--) sa[cnt[x[y[i]]]--]=y[i]; 20 for(R int i=1;i<=m;i++) cnt[i]=0; 21 swap(x,y); 22 x[sa[1]]=num=1; 23 for(R int i=2;i<=n;i++){ 24 if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) num++; 25 x[sa[i]]=num; 26 } 27 if(num>=n) break; 28 m=num; 29 } 30 for(R int i=1;i<=n;i++) rank[sa[i]]=i; 31 int t=0; 32 for(R int i=1;i<=n;i++){ 33 if(t) t--; 34 while(rank[i]-1&&s[i+t]==s[sa[rank[i]-1]+t]) t++; 35 h[i]=t,height[rank[i]]=t; 36 } 37 } 38 bool vis[N]; 39 bool check(int k){ 40 memset(vis,0,sizeof(vis)); 41 vis[0]=1; 42 int minh=oo,cc=0; 43 for(int i=1;i<=n;i++){ 44 minh=min(minh,height[i]); 45 if(minh<k){ 46 memset(vis,0,sizeof(vis)); 47 vis[0]=1; 48 cc=0,minh=oo; 49 }else{ 50 if(!vis[bel[sa[i]]]) vis[bel[sa[i]]]=1,cc++; 51 if(i>=1&&!vis[bel[sa[i-1]]]) vis[bel[sa[i-1]]]=1,cc++; 52 if(cc>=tot) return 1; 53 } 54 } 55 return 0; 56 } 57 int main(){ 58 int t1,t2,t3,div=1000000000; 59 scanf("%d",&tot); 60 for(R int i=1;i<=tot;i++){ 61 scanf("%d%d",&t1,&t2); 62 for(int j=1;j<t1;j++) scanf("%d",&t3),a[++n]=t3-t2,x[n]=a[n],t2=t3,bel[n]=i,numpos[n]=n; 63 a[++n]=++div,numpos[n]=n; 64 } 65 sort(numpos+1,numpos+n+1,cmp); 66 int temp=0; 67 x[numpos[1]]=s[numpos[1]]=++temp; 68 for(int i=2;i<=n;i++){ 69 if(a[numpos[i]]!=a[numpos[i-1]]) temp++; 70 s[numpos[i]]=x[numpos[i]]=temp; 71 } 72 m=temp; 73 build(); 74 int l=0,r=n,ans=0; 75 while(l<=r){ 76 int mid=(l+r)>>1; 77 if(check(mid)) l=mid+1,ans=mid; 78 else r=mid-1; 79 } 80 printf("%d",ans+1); 81 return 0; 82 }