我们先处理出两个哈希矩阵,分别代表初始矩阵,转180°后的矩阵。在统计答案时,枚举每个中心点,二分正方形的长度的一半,利用之前处理好的二维哈希值进行O(1)判断。(注意,正方形长度需要分奇偶讨论)
时间复杂度:O(n^2 log n)
#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int N= 305 ;
const int base1= 131 , base2= 83 ;
int n, m, l, r, mid, ans, sum;
int bin1[ N] , bin2[ N] , a[ N] [ N] , b[ N] [ N] , sum1[ N] [ N] , sum2[ N] [ N] ;
inline bool jay ( int x, int y, int len)
{
if ( x> n || y> m) return false ;
if ( x< len || y< len) return false ;
int xx= x, yy= y;
int ans1= sum1[ x] [ y] - sum1[ x- len] [ y] * bin1[ len] - sum1[ x] [ y- len] * bin2[ len] + sum1[ x- len] [ y- len] * bin1[ len] * bin2[ len] ;
x= n- ( x- len) ; y= m- ( y- len) ;
int ans2= sum2[ x] [ y] - sum2[ x- len] [ y] * bin1[ len] - sum2[ x] [ y- len] * bin2[ len] + sum2[ x- len] [ y- len] * bin1[ len] * bin2[ len] ;
if ( ans1!= ans2) return false ;
return true ;
}
signed main ( ) {
scanf ( "%lld%lld" , & n, & m) ;
bin1[ 0 ] = bin2[ 0 ] = 1 ;
for ( register int i= 1 ; i<= n; ++ i) bin1[ i] = bin1[ i- 1 ] * base1;
for ( register int i= 1 ; i<= m; ++ i) bin2[ i] = bin2[ i- 1 ] * base2;
for ( register int i= 1 ; i<= n; ++ i)
for ( register int j= 1 ; j<= m; ++ j) scanf ( "%1lld" , & a[ i] [ j] ) ;
for ( register int i= 1 ; i<= n; ++ i)
for ( register int j= 1 ; j<= m; ++ j) sum1[ i] [ j] = sum1[ i] [ j- 1 ] * base2+ a[ i] [ j] ;
for ( register int i= 1 ; i<= n; ++ i)
for ( register int j= 1 ; j<= m; ++ j) sum1[ i] [ j] + = sum1[ i- 1 ] [ j] * base1;
for ( register int i= 1 ; i<= n; ++ i)
for ( register int j= 1 ; j<= m; ++ j) b[ i] [ j] = a[ n- i+ 1 ] [ m- j+ 1 ] ;
for ( register int i= 1 ; i<= n; ++ i)
for ( register int j= 1 ; j<= m; ++ j) sum2[ i] [ j] = sum2[ i] [ j- 1 ] * base2+ b[ i] [ j] ;
for ( register int i= 1 ; i<= n; ++ i)
for ( register int j= 1 ; j<= m; ++ j) sum2[ i] [ j] + = sum2[ i- 1 ] [ j] * base1;
for ( register int i= 1 ; i<= n; ++ i)
for ( register int j= 1 ; j<= m; ++ j)
{
l= 1 ; r= min ( n, m) ; ans= 0 ;
while ( l<= r)
{
mid= l+ r>> 1 ;
if ( jay ( i+ mid, j+ mid, mid+ mid+ 1 ) ) ans= mid, l= mid+ 1 ;
else r= mid- 1 ;
}
sum= max ( sum, ans+ ans+ 1 ) ;
}
for ( register int i= 1 ; i< n; ++ i)
for ( register int j= 1 ; j< m; ++ j)
{
l= 1 ; r= min ( n, m) ; ans= 0 ;
while ( l<= r)
{
mid= l+ r>> 1 ;
if ( jay ( i+ mid, j+ mid, mid+ mid) ) ans= mid, l= mid+ 1 ;
else r= mid- 1 ;
}
sum= max ( sum, ans+ ans) ;
}
if ( sum> 1 ) printf ( "%lld\n" , sum) ;
else puts ( "-1" ) ;
return 0 ;
}