分析:
这道题就是一道二维字符串hash的模板题,学习下二维字符串hash,将图中的每一个子矩阵的hash值预处理出来,然后用二分答案去判断是否存在两个hash值相同的正方形即可.
这里直接给出二维字符串hash计算模板
一维hash是把一个字符串用一个整数表示,二维hash是把一个矩阵用一个整数表示。
void init(){
p1[0] = p2[0] = 1;
for(int i=1;i<505;i++){
p1[i] = p1[i-1]*base1;
p2[i] = p2[i-1]*base2;
}
return ;
}
void get_Hash(){
//Hash公式 Hash[i][j] = Hash[i][j-1]*base1+Hash[i-1][j]*base2+a[i][j]
//先横着Hash
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
Hash[i][j] = Hash[i][j-1]*base1+s[i][j];
}
//再竖着Hash,此时的hash[i][j]= Hash[i][j-1]*base1+s[i][j]
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
Hash[i][j]+=Hash[i-1][j]*base2;
}
}
计算右下角为(x,y),长度为Size正方形的hash值
for(int i=Size;i<=n;i++)
for(int j=Size;j<=m;j++){
ll k = Hash[i][j]-Hash[i-Size][j]*p2[Size]-Hash[i][j-Size]*p1[Size];
k+=Hash[i-Size][j-Size]*p1[Size]*p2[Size];
mp[k]++;
if(mp[k]==2) return true;
//这里的k就是hash值,求法类似于求二维前缀和的方法
}
AC_Code:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;//unsigned long long ll自溢出功能,溢出后对自己取模
//找一个base1和base2都是相对大的素数,减小hash冲突的概率
ll base1 = 92083;
ll base2 = 69061;
const int Maxn = 505;
ll p1[Maxn],p2[Maxn];
ll Hash[Maxn][Maxn];
map<ll,ll>mp;
int n,m;
char s[Maxn][Maxn];
void init(){
p1[0] = p2[0] = 1;
for(int i=1;i<505;i++){
p1[i] = p1[i-1]*base1;
p2[i] = p2[i-1]*base2;
}
return ;
}
void get_Hash(){
//Hash公式 Hash[i][j] = Hash[i][j-1]*base1+Hash[i-1][j]*base2+a[i][j]
//先横着Hash
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
Hash[i][j] = Hash[i][j-1]*base1+s[i][j];
}
//再竖着Hash,此时的hash[i][j]= Hash[i][j-1]*base1+s[i][j]
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
Hash[i][j]+=Hash[i-1][j]*base2;
}
}
bool check(int Size){
mp.clear();
//这里计算右下角为(x,y)边长为Size的正方形的hash值,类似于二维前缀和
for(int i=Size;i<=n;i++)
for(int j=Size;j<=m;j++){
ll k = Hash[i][j]-Hash[i-Size][j]*p2[Size]-Hash[i][j-Size]*p1[Size];
k+=Hash[i-Size][j-Size]*p1[Size]*p2[Size];
mp[k]++;
if(mp[k]==2) return true;
}
return false;
}
int main(){
init();
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
get_Hash();//一定要放到输入数据后面
int l = 1,r = min(n,m);
int ans = 0;
while(l<=r){
int mid = l+r>>1;
if(check(mid)){
ans = mid;
l = mid+1;
}
else r = mid-1;
}
cout<<ans<<'\n';
return 0;
}