题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1567
题面大意:给你两个矩阵,求最大公共正方形矩阵边长
二分边长,对于每个正方形直接Hash出一个值,扔进map里,然后验证,时间复杂度O(n^2logn)
#include <iostream>
#include <map>
#define douM 233333333
#define Mdou 666666666
#define u unsigned int
using namespace std;
unsigned int a[100][100],b[100][100],cf1[100],cf2[100];
map<unsigned int,int> Hash;
int n,cnt = 0,T;
bool judge(int x)
{
cnt ++;
for(int i = x;i <= n;i ++)
for(int j = x;j <= n;j ++)
{
unsigned int h = a[i][j];
h -= a[i-x][j] * cf1[x];
h -= a[i][j-x] * cf2[x];
h += a[i-x][j-x] * cf1[x] * cf2[x];
Hash[h] = cnt;
}
for(int i = x;i <= n;i ++)
for(int j = x;j <= n;j ++)
{
unsigned int h = b[i][j];
h -= b[i-x][j] * cf1[x];
h -= b[i][j-x] * cf2[x];
h += b[i-x][j-x] * cf1[x] * cf2[x];
if(Hash[h] == cnt)
return 1;
}
return 0;
}
int ef()
{
int l = 0,r = n;
while(l + 1 < r)
{
int mid = (l+r)/2;
if(judge(mid))
l = mid;
else
r = mid;
}
if(judge(r))
return r;
return l;
}
int main()
{
cin >> n;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
cin >> a[i][j];
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
a[i][j] += a[i-1][j] * douM;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
a[i][j] += a[i][j-1] * Mdou;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
cin >> b[i][j];
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
b[i][j] += b[i-1][j] * douM;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
b[i][j] += b[i][j-1] * Mdou;
cf1[0] = 1;
cf2[0] = 1;
for(int i = 1;i <= 70;i ++)
{
cf1[i] = cf1[i-1] * douM;
cf2[i] = cf2[i-1] * Mdou;
}
cout << ef() << endl;
return 0;
}