哈希水过。
首先这是一段delta相同的序列,按照套路差分一下,b[i]=a[i]-a[i-1],然后就是这些序列的最长公共子段
由于数据范围很小,就可以二分,枚举第一个序列的子段然后每个子序列暴力check,跑得飞快。
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,M[1001],A[1001][102];
ll Hash1[1001][102],Base1[102],Mod1=998244853;
ll Hash2[1001][102],Base2[102],Mod2=1000000009;
il std::pair<ll,ll> Query(int x,int l,int r){
return
std::make_pair(
(Hash1[x][r]-Hash1[x][l-1]+Mod1)*Base1[101-r]%Mod1,
(Hash2[x][r]-Hash2[x][l-1]+Mod2)*Base2[101-r]%Mod2
);
}
il bool check(int mid){
for(int l=1;l+mid-1<=M[1];++l){
std::pair<ll,ll>s=Query(1,l,l+mid-1);
for(int i=2;i<=n;++i){
bool flg=0;
for(int j=1;j+mid-1<=M[i];++j)
if(Query(i,j,j+mid-1)==s)
{flg=1;break;}
if(!flg)goto GG;
}
return 1;
GG:;
}
return 0;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("2463.in","r",stdin);
freopen("2463.out","w",stdout);
#endif
n=gi();
int l=0,r=1e9,mid;
Base1[0]=1;for(int i=1;i<=101;++i)Base1[i]=Base1[i-1]*19260817%Mod1;
Base2[0]=1;for(int i=1;i<=101;++i)Base2[i]=Base2[i-1]*23333%Mod2;
for(int i=1;i<=n;++i){
M[i]=gi();r=std::min(r,M[i]-1);
for(int j=1;j<=M[i];++j)A[i][j]=gi();
for(int j=M[i];j>1;--j)A[i][j]-=A[i][j-1];
for(int j=1;j<=M[i];++j)Hash1[i][j]=(Hash1[i][j-1]+A[i][j]*Base1[j]%Mod1+Mod1)%Mod1;
for(int j=1;j<=M[i];++j)Hash2[i][j]=(Hash2[i][j-1]+A[i][j]*Base2[j]%Mod2+Mod2)%Mod2;
}
while(l<r){
mid=(l+r)>>1;
if(check(mid+1))l=mid+1;
else r=mid;
}
printf("%d
",l+1);
return 0;
}