传送门
听说数据水???
其实这题更水好吧
题意:
求
n
n
n个数字串的最长公共子串长度。
两个子串相同的定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串
思路:
假如没有那个定义,把所有字符串拼在一起建一个
S
A
SA
SA,中间用特殊字符连接,然后二分答案+双指针
c
h
e
c
k
check
check就完了。 废话
现在考虑如何转化相等这个条件。
假设两个串为
a
1
,
a
2
,
.
.
.
,
a
k
a_1,a_2,...,a_k
a1,a2,...,ak和
b
1
,
b
2
,
.
.
.
,
b
k
b_1,b_2,...,b_k
b1,b2,...,bk
那么他们相等的条件等价于是
∏
[
a
i
−
a
i
−
1
=
=
b
i
−
b
i
−
1
,
i
>
1
]
\prod[a_i-a_{i-1}==b_i-b_{i-1},i>1]
∏[ai−ai−1==bi−bi−1,i>1]
这样我们用一个串的差分数组来代替它然后二分答案即可,注意处理每个串的第一个数字。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int N=1005,M=2e5+5;
int n,s[M],m,len,t[M],up=1e9,pos[M],a[M];
namespace SA{
int m,sa[M],sa2[M],rk[M],ht[M];
inline void Sort(){
static int cnt[M];
for(ri i=1;i<=m;++i)cnt[i]=0;
for(ri i=1;i<=n;++i)++cnt[rk[i]];
for(ri i=1;i<=m;++i)cnt[i]+=cnt[i-1];
for(ri i=n;i;--i)sa[cnt[rk[sa2[i]]]--]=sa2[i];
}
inline void getSA(){
for(ri i=1;i<=n;++i)rk[i]=s[i],sa2[i]=i;
m=7000;
Sort();
for(ri w=1,p=0;m^n;w<<=1,p=0){
for(ri i=n-w+1;i<=n;++i)sa2[++p]=i;
for(ri i=1;i<=n;++i)(sa[i]>w)&&(sa2[++p]=sa[i]-w);
Sort(),swap(rk,sa2);
rk[sa[p=1]]=1;
for(ri i=2;i<=n;++i)rk[sa[i]]=(sa2[sa[i]]==sa2[sa[i-1]]&&sa2[sa[i]+w]==sa2[sa[i-1]+w])?p:++p;
m=p;
}
for(ri i=1,j,k=0;i<=n;ht[rk[i++]]=k)for(k?--k:k,j=sa[rk[i]-1];s[i+k]==s[j+k];++k);
}
inline bool check(int len,int m){
static int tot[N];
for(ri ss,l=2,r;l<=n;l=r+1){
while(l<n&&ht[l]<len)++l;
if(ht[l]<len)break;
r=l;
while(r<n&&ht[r+1]>=len)++r;
ss=0;
for(ri i=l-1;i<=r;++i){
if(!pos[sa[i]])continue;
if(!tot[pos[sa[i]]])++ss;
++tot[pos[sa[i]]];
}
for(ri i=l-1;i<=r;++i)if(pos[sa[i]])--tot[pos[sa[i]]];
if(ss==m)return 1;
}
return 0;
}
inline void solve(int m){
getSA();
int l=0,r=up-1,res=0;
while(l<=r){
int mid=l+r>>1;
if(check(mid,m))l=mid+1,res=mid;
else r=mid-1;
}
cout<<res+1;
}
}
int main(){
freopen("lx.in","r",stdin);
m=read();
if(m==1)return cout<<read(),0;
for(ri idx=4000,tt,i=1;i<=m;++i){
s[++n]=++idx;
up=min(up,tt=read());
for(ri j=1;j<=tt;++j)a[j]=read();
for(ri j=tt;j;--j)a[j]-=a[j-1]-2000;
a[1]=++idx;
for(ri j=1;j<=tt;++j)s[++n]=a[j],pos[n]=i;
}
SA::solve(m);
return 0;
}