二分后判定有无两个相同的子正方形,复习了一下二维字符串哈希。
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define ull unsigned long long #define inf 1e9 #define eps 1e-10 #define md #define N 55 #define H 100010 using namespace std; int n; ull a[N][N],b[N][N],suma[N][N],sumb[N][N],mi1[N],mi2[N]; const ull cheng1=233333333,cheng2=987654321; struct ha { ull a[H]; bool vis[H]; void clear() { memset(vis,0,sizeof(vis)); } void insert(ull x) { int pos=x%H; while (vis[pos]) { pos++; if (pos>=H) pos-=H; } vis[pos]=1; a[pos]=x; } bool find(ull x) { int pos=x%H; while (vis[pos]&&a[pos]!=x) { pos++; if (pos>=H) pos-=H; } return vis[pos]; } } hash; void buildha() { for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) suma[i][j]=suma[i][j-1]*cheng1+a[i][j]; } for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) suma[i][j]=suma[i-1][j]*cheng2+suma[i][j]; } for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) sumb[i][j]=sumb[i][j-1]*cheng1+b[i][j]; } for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) sumb[i][j]=sumb[i-1][j]*cheng2+sumb[i][j]; } mi1[0]=1; for (int i=1;i<=n;i++) mi1[i]=mi1[i-1]*cheng1; mi2[0]=1; for (int i=1;i<=n;i++) mi2[i]=mi2[i-1]*cheng2; } bool ok(int r) { hash.clear(); for (int i=r;i<=n;i++) for (int j=r;j<=n;j++) hash.insert(suma[i][j]-suma[i][j-r]*mi1[r]-suma[i-r][j]*mi2[r]+suma[i-r][j-r]*mi1[r]*mi2[r]); for (int i=r;i<=n;i++) for (int j=r;j<=n;j++) if (hash.find(sumb[i][j]-sumb[i][j-r]*mi1[r]-sumb[i-r][j]*mi2[r]+sumb[i-r][j-r]*mi1[r]*mi2[r])) return 1; return 0; } int main() { #ifndef ONLINE_JUDGE freopen("data.in","r",stdin); freopen("data.out","w",stdout); #endif scanf("%d",&n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%llu",&a[i][j]); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%llu",&b[i][j]); buildha(); int l=0,r=n; while (l!=r) { int mid=(l+r+1)>>1; if (ok(mid)) l=mid; else r=mid-1; } printf("%d\n",l); return 0; }