题目大意:
给你n个串\(s_1\sim s_n\),要你在每个串中找一个长度为k的子串,满足任意\(1\leqslant i<k\),有\(s_1[i+1]-s_1[i]=s_2[i+1]-s_2[i]=\dots=s_n[i+1]-s_n[i]\)。问满足条件的k最大是多少。
解题思路:
相邻两个数差相等,我们先将原串进行差分。
然后首尾相连求后缀数组(中间用分隔符隔开)。
二分答案。对于答案t,考虑height数组中所有连续的,且大于等于t的子区间,若包含1~n所有串,则答案可行。
由于进行了差分,最后答案+1即可。
C++ Code:
#include<bits/stdc++.h>
const int NN=1200005;
inline int readint(){
int c=getchar(),d=0,f=0;
for(;!isdigit(c);c=getchar())f=c=='-';
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return f?-d:d;
}
int N,s[NN],n=0,a[1005],fg=30005,t1[NN],t2[NN],c[NN],rk[NN],height[NN],belong[NN],sa[NN];
bool vis[1005];
inline void sa_sort(){
int*x=t1,*y=t2,m=60000;
memset(c,0,sizeof c);
for(int i=1;i<=n;++i)++c[x[i]=s[i]];
for(int i=1;i<=m;++i)c[i]+=c[i-1];
for(int i=n;i;--i)sa[c[x[i]]--]=i;
for(int k=1;k<=n;k<<=1){
int p=0;
for(int i=n-k+1;i<=n;++i)y[++p]=i;
for(int i=1;i<=n;++i)if(sa[i]>k)y[++p]=sa[i]-k;
for(int i=0;i<=m;++i)c[i]=0;
for(int i=1;i<=n;++i)++c[x[y[i]]];
for(int i=1;i<=m;++i)c[i]+=c[i-1];
for(int i=n;i;--i)sa[c[x[y[i]]]--]=y[i];
int*tmp=x;x=y,y=tmp;
x[sa[p=1]]=1;
for(int i=2;i<=n;++i)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p:++p;
if(p==n)break;
m=p;
}
}
inline void get_height(){
for(int i=1;i<=n;++i)rk[sa[i]]=i;
for(int i=1,k=0;i<=n;++i)
if(rk[i]!=1){
if(k)--k;
int j=sa[rk[i]-1];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])++k;
height[rk[i]]=k;
}
}
inline bool check(int k){
memset(vis,0,sizeof vis);
int ok=1;
vis[belong[sa[1]]]=1;
for(int i=2;i<=n;++i){
if(height[i]>=k){
if(!vis[belong[sa[i]]]){
vis[belong[sa[i]]]=1;
if(++ok>=N)return 1;
}
}else{
int j;
for(j=i-1;j&&height[j]>=k;--j)
vis[belong[sa[j]]]=0;
vis[belong[sa[j]]]=0;
vis[belong[sa[i]]]=1;
ok=1;
}
if(!belong[sa[i]])break;
}
return 0;
}
int main(){
N=readint();
for(int i=1;i<=N;++i){
int nn=readint();
for(int j=0;j<nn;++j)a[j]=readint();
for(int j=nn-1;j;--j)a[j]-=a[j-1];
for(int j=1;j<nn;++j)s[++n]=a[j]+10001,belong[n]=i;
s[++n]=fg++;
}
sa_sort();
get_height();
int l=1,r=1001,ans=0;
while(l<=r){
int mid=l+r>>1;
if(check(mid))l=(ans=mid)+1;else
r=mid-1;
}
printf("%d\n",ans+1);
return 0;
}