Significado del título
Dada una matriz n*m. Deja que encuentres el cuadrado más grande de ellos. Tal cuadrado aparece al menos dos veces en la matriz. Muestra la longitud del lado del cuadrado más grande.
analizar
El punto clave de esta pregunta es cómo definir un cuadrado.Si simplemente vas a la violencia y analizas la matriz fila por fila, entonces la complejidad llegará a O(n 3 ).Si conoces el hash bidimensional, entonces puedes obtener el valor hash del cuadrado Se obtiene bajo la complejidad temporal de O(1).
La clave del hashing bidimensional es definir y obtener, lo cual se define de la siguiente manera:
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
hasha[i][j]=hasha[i][j-1]*base1+a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
hasha[i][j]+=hasha[i-1][j]*base2;
Consíguelo de la siguiente manera:
k = Hash[i][j]-Hash[i][j-x]*hash1[x]-Hash[i-x][j]*hash2[x]+Hash[i-x][j-x]*hash1[x]*hash2[x];
//这个的意思就是右下角为(i,j),边长为x的正方形
La primera vez es hacer hash horizontalmente, usando base 1. En este momento, hash[i][j] representa el valor hash de la cadena de prefijos cuya longitud es j en la i-ésima línea.
La segunda vez es el hash vertical, usando base2, en este momento el hash[i][j] se ha actualizado, y el hash[i][j] en este momento se ha convertido (1, 1) en (i-1 , j) El valor hash de la matriz * base2 + el valor hash de la cadena de prefijos cuya longitud es j en la i-ésima fila, que representa el valor hash de la matriz de (1, 1) a (i, j) .
Luego, al calcular el valor hash de una submatriz, por ejemplo, las coordenadas de la esquina inferior derecha de la submatriz son (i, j), el número de filas es n y el número de columnas es m, entonces el valor hash de la submatriz es hash[i][j]-hash[in][j]*base1 n -hash[i][jm]*base2 m +hash[in][jm]*base1 n *base2 m (Esto es similar a la suma de prefijos bidimensionales).
Entonces este problema se dará cuenta.
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cstring>
#include <stack>
#include <string>
using namespace std;
typedef unsigned long long ll;
const int N = 1e5+199;
const double Pi = acos(-1);
int n,m;
char e[600][600];
map<ll,bool>ma;
ll base1 = 131, base2 = 137, hash1[510], hash2[510], Hash[510][510];
bool Check(int x){
for(int i=x;i<=n;i++){
for(int j=x;j<=m;j++){
ll k = Hash[i][j]-Hash[i][j-x]*hash1[x]-Hash[i-x][j]*hash2[x]+Hash[i-x][j-x]*hash1[x]*hash2[x];
// cout<<k<<endl;
if(ma[k])
return true;
else
ma[k]=1;
}
}
return false;
}
void Init(){
hash1[0]=hash2[0]=1;
for(int i=1;i<=500;i++){
hash1[i] = hash1[i-1]*base1;
hash2[i] = hash2[i-1]*base2;
}
for(int i=1;i<=n;i++){
//对每一行进行哈希
for(int j=1;j<=m;j++){
Hash[i][j]=Hash[i][j-1]*base1 + e[i][j]-'a'+1;
}
}
for(int i=1;i<=n;i++){
//类似二维求和,相当于对每一列哈希
for(int j=1;j<=m;j++){
Hash[i][j]+=Hash[i-1][j]*base2;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d%d\n",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",e[i]+1);
Init();
int lb=1,ub=min(n,m),mid;
while(lb<=ub){
mid = (lb+ub)>>1;
if(Check(mid))
lb = mid+1;
else
ub = mid-1;
ma.clear();
// cout<<mid<<endl;
}
printf("%d\n",lb-1);
return 0;
}