差分过后就是求最长公共子串了,无数多倍经验了...
具体可以见P5546 [POI2000]公共串
但是这道题要魔改一下就是:
(1.) 第一项可以不匹配,于是输出 (ans+1)
(2.) 因为这里值域很大,所以用 (map) 代替数组。
代码:
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
const int N=3e5+5,INF=1e9+7;
int x,n,a[N],last=1,tot=1,Ans[N<<1],AAns[N<<1],ans,c[N],q[N<<1];
bool flag;
char str[N];
struct SAM{
unordered_map<int,int>son;
int fa,len;
}t[N<<1];
void Extend(int c){
int p=last,np=++tot;last=np;
t[np].len=t[p].len+1;
while(p&&!t[p].son[c]) t[p].son[c]=np,p=t[p].fa;
if(!p) t[np].fa=1;
else{
int q=t[p].son[c];
if(t[p].len+1==t[q].len) t[np].fa=q;
else{
int nq=++tot;
t[nq]=t[q];t[nq].len=t[p].len+1;
t[np].fa=t[q].fa=nq;
while(p&&t[p].son[c]==q) t[p].son[c]=nq,p=t[p].fa;
}
}
return ;
}
int Len;
void Search(int &x,int c){
if(t[x].son[c]) Len++,x=t[x].son[c],AAns[x]=max(AAns[x],Len);
else{
int p=x;
while(p&&!t[p].son[c]) p=t[p].fa;
if(!p) x=1,Len=0;
else x=t[p].son[c],Len=t[p].len+1,AAns[x]=max(AAns[x],Len);
}
return ;
}
int main(){
read(n);
int len;read(len);
for(int i=1;i<=len;i++) read(a[i]);
for(int i=1;i<=len;i++) Extend(a[i]-a[i-1]);
for(int i=1;i<=tot;i++) c[t[i].len]++;
for(int i=1;i<=tot;i++) c[i]+=c[i-1];
for(int i=1;i<=tot;i++) q[c[t[i].len]--]=i;
for(int i=0;i<=tot;i++) Ans[i]=INF;
n--;
while(n--){
read(len);
for(int i=1;i<=len;i++) read(a[i]);
for(int i=1,now=1;i<=len;i++) Search(now,a[i]-a[i-1]);
for(int i=tot;i>=1;i--){
int x=q[i];
AAns[t[x].fa]=max(AAns[t[x].fa],min(AAns[x],t[t[x].fa].len));
Ans[x]=min(Ans[x],AAns[x]);AAns[x]=0;
}
}
for(int i=1;i<=tot;i++) ans=max(ans,Ans[i]);
write(ans+1);
return 0;
}