传送门
二分答案+哈希。
二分边长,哈希判断是否相等。
注意,行/列上计算key时乘的数应不同。
#include<cstring>
#include<cmath>
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
ll a[2][55][55],f[2][55][55],t[55],b[2505];
int n,l,r,m,ans;
inline ll read(){
ll x=0,f=1;
char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-48;
return x*f;
}
inline ll cal(int x,int y,int z,int m){
ll val=1;
for (int i=y;i<y+m;i++)
val=val*3659+f[x][i][z+m-1]-f[x][i][z-1]*t[m];
return val;
}
inline int jud(int m){
int cnt=0;
for (int i=1;i<=n-m+1;i++)
for (int j=1;j<=n-m+1;j++)
b[++cnt]=cal(0,i,j,m);
sort(b+1,b+cnt+1);
for (int i=1;i<=n-m+1;i++)
for (int j=1;j<=n-m+1;j++){
ll t=cal(1,i,j,m);
if (*lower_bound(b+1,b+cnt+1,t)==t) return 1;
}
return 0;
}
int main(){
n=read();
t[0]=1;
for (int i=1;i<=n;i++) t[i]=t[i-1]*1789;
for (int i=0;i<2;i++)
for (int j=1;j<=n;j++)
for (int k=1;k<=n;k++) a[i][j][k]=read();
for (int i=0;i<2;i++)
for (int j=1;j<=n;j++){
f[i][j][0]=1;
for (int k=1;k<=n;k++) f[i][j][k]=f[i][j][k-1]*1789+a[i][j][k];
}
l=1,r=n;
while (l<=r){
m=(l+r)/2;
if (jud(m)) ans=m,l=m+1;
else r=m-1;
}
printf("%d",ans);
}