Matriz de Niuke hash bidimensional + binario

enlace de tema

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;
}

Supongo que te gusta

Origin blog.csdn.net/c___c18/article/details/115545503
Recomendado
Clasificación