是上面那题的加强版,数据范围变大了,题目要求也稍微改动了一下。
其实我们只要把原数组变成一个差量数组,同时在哈希的时候,避免负数就好了。
时间复杂度:O(log2(m) nm log2(nm))
#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int N=1e3+5,M=105,base=131;
int n,l,r,mid,ans;
int len[N],hash[N][M],sum[N][M],bin[M],num[M];
map<int,bool>mp[N];
inline int get(int x,int y,int id){return hash[id][y]-hash[id][x-1]*bin[y-x+1];}
inline void init()
{
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=len[i]-mid+1; ++j) mp[i][sum[i][j]]=false;
}
inline bool jay(int mid)
{
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=len[i]-mid+1; ++j) sum[i][j]=get(j,j+mid-1,i),mp[i][sum[i][j]]=true;
for (register int i=1; i<=len[1]-mid+1; ++i)
{
bool flag=true;
for (register int j=2; j<=n; ++j) if (!mp[j][sum[1][i]]) {flag=false; break;}
if (flag)
{
init();
return true;
}
}
init();
return false;
}
signed main(){
scanf("%lld",&n);
l=1e9; r=0;
for (register int i=1; i<=n; ++i)
{
scanf("%lld",&len[i]);
for (register int j=1; j<=len[i]; ++j) scanf("%lld",&num[j]);
len[i]--;
l=min(l,len[i]); r=max(r,len[i]);
for (register int j=1; j<=len[i]; ++j) num[j]=num[j]-num[j+1]+2000;
for (register int j=1; j<=len[i]; ++j) hash[i][j]=hash[i][j-1]*base+num[j];
}
bin[0]=1;
for (register int i=1; i<=r; ++i) bin[i]=bin[i-1]*base;
r=l; l=1;
while (l<=r)
{
mid=l+r>>1;
if (jay(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
ans++;
printf("%lld\n",ans);
return 0;
}