考虑这是一个0 1矩阵 我们对每一行进行 hash ,再对每一列进行 hash ,取两个不同的 base ,这样可以一定程度上保证 hash 的正确性,由于蒟蒻我比较菜,没有写散列表,只能 RP++RP++ 看有没有重复了,横行 d[i][j]=d[i][j-1]base1+a[i][j]d[i][j]=d[i][j−1]∗base1+a[i][j] ,再考虑竖列 sum[i][j]=sum[i-1][j]*base2+d[i][j]sum[i][j]=sum[i−1][j]∗base2+d[i][j] ,再将矩阵整个旋转 180°,如果一个子正方形旋转前和旋转后的 hash 值相同,则大概率下,这两个矩阵相同。我们枚举方阵的边长(注意不能二分,这玩意坑了我很久,我二分一直 WA ,仔细一想发现如果前面不满足,后面满足的情况也是存在的,不满足单调性),枚举矩阵的点,进行 hash判断,时间复杂度O(N³),下面贴代码
//看了看AC记录,貌似 RANK1 ,比 RANK2 快了差不多10倍?其实这题二进制压缩貌似也可做?不过工程量巨大?不管了, QAQ
// 可能代码略丑,借鉴思路即可。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef unsigned long long ll;
ll base1=131,base2=233;
ll re(){
char c=getchar();ll all=0,pd=1;
for(;c>'9'||c<'0';c=getchar()) if(c=='-') pd=-1;
while(c>='0'&&c<='9') all=all*10+c-'0',c=getchar();return all*pd;
}const ll N=305;
char s[N];ll a[N][N],d[N][N],sum[N][N],aa[N][N],sum2[N][N],n,m,qpow1[N],qpow2[N];
ll cal(ll x,ll y,ll l,ll type){
if(type==1) return sum[x][y]-sum[x-l][y]*qpow2[l]-sum[x][y-l]*qpow1[l]+sum[x-l][y-l]*qpow1[l]*qpow2[l];
y=m+l-y,x=n+l-x;
return sum2[x][y]-sum2[x-l][y]*qpow2[l]-sum2[x][y-l]*qpow1[l]+sum2[x-l][y-l]*qpow1[l]*qpow2[l];
}
ll work(ll l){
for(ll i=l;i<=n;i++)
for(ll j=l;j<=m;j++)
if(cal(i,j,l,1)==cal(i,j,l,2)) return 1;
return 0;
}ll ans=0;
int main(){
n=re(),m=re();
for(ll i=1;i<=n;i++){
scanf("%s",s+1);
for(ll j=1;j<=(ll)strlen(s+1);j++)
a[i][j]=s[j]-'0';
}
qpow1[0]=1;for(int i=1;i<=300;i++) qpow1[i]=qpow1[i-1]*base1;
qpow2[0]=1;for(int i=1;i<=300;i++) qpow2[i]=qpow2[i-1]*base2;
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
d[i][j]=d[i][j-1]*base1+a[i][j];
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
sum[i][j]=sum[i-1][j]*base2+d[i][j];
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
aa[i][j]=a[n-i+1][m-j+1];
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
d[i][j]=d[i][j-1]*base1+aa[i][j];
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
sum2[i][j]=sum2[i-1][j]*base2+d[i][j];
for(int i=1;i<=max(n,m);i++)
if(work(i)) ans=i;
if(ans!=1&&ans!=0)printf("%llu",ans);
else printf("-1
");
}