思路:
直接四重循环枚举右下角,然后二分长度hash判断
c o d e code code
#include<iostream>
#include<cstdio>
using namespace std;
unsigned long long mod1=1000000007ull, mod2=1000000009ull;
int n;
unsigned long long hasha[100][100], hashb[100][100];
unsigned long long p1[100], p2[100];
bool check(int mid, int x, int y, int xx, int yy)
{
if(x-mid<0||y-mid<0||xx-mid<0||yy-mid<0)
return 0;
unsigned long long sa=hasha[x][y]-hasha[x-mid][y]*p2[mid]-hasha[x][y-mid]*p1[mid]+hasha[x-mid][y-mid]*p1[mid]*p2[mid];
unsigned long long sb=hashb[xx][yy]-hashb[xx-mid][yy]*p2[mid]-hashb[xx][yy-mid]*p1[mid]+hashb[xx-mid][yy-mid]*p1[mid]*p2[mid];
return sa==sb;
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d", &hasha[i][j]);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d", &hashb[i][j]);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
hasha[i][j]+=hasha[i][j-1]*mod1;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
hasha[i][j]+=hasha[i-1][j]*mod2;
p1[0]=p2[0]=1ull;
for(int i=1; i<=n; i++)
p1[i]=p1[i-1]*mod1, p2[i]=p2[i-1]*mod2;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
hashb[i][j]+=hashb[i][j-1]*mod1;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
hashb[i][j]+=hashb[i-1][j]*mod2;
int ans=0;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
for(int i1=1; i1<=n; i1++)
for(int j1=1; j1<=n; j1++)
{
int l=0, r=n;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid, i, j, i1, j1))
{
ans=max(ans, mid);
l=mid+1;
}
else
r=mid-1;
}
}
printf("%d", ans);
return 0;
}