牛客练习赛1-A 矩阵

题目

给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。

输入描述

第一行两个整数n,m代表矩阵的长和宽;

接下来n行,每行m个字符(小写字母),代表矩阵;

输出描述

输出一个整数表示最大正方形的边长。

分析

显然,这是一个字符串hash的题目;

唯一的难点的就是这个hash方式,get了。

code

#include<bits/stdc++.h>

using namespace std;

#define ull unsigned long long
#define ll long long
#define pi acos(-1.0)
#define inf 0x3f3f3f3f
#define maxn 555
#define mod 100007

struct Edge{
    ull v;
    int nxt;
}e[maxn*maxn];
int head[mod];
ull base1=1313,base2=13131;
ull hash1[maxn][maxn],hash2[maxn][maxn];
ull bit1[maxn],bit2[maxn];
char s[maxn][maxn];
int n,m,cnt;

void init(){
    bit1[0]=bit2[0]=1;
    for(int i=1;i<maxn;i++){
        bit1[i]=bit1[i-1]*base1;
        bit2[i]=bit2[i-1]*base2;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            hash1[i][j]=hash1[i][j-1]*base1+s[i][j];
            hash2[i][j]=hash2[i-1][j]*base2+hash1[i][j];
        }
    }
}

ull cal(int i,int j,int x){
    ull ret=hash2[i+x-1][j+x-1];
    ret-=hash2[i+x-1][j-1]*bit1[x]+hash2[i-1][j+x-1]*bit2[x];
    ret+=hash2[i-1][j-1]*bit1[x]*bit2[x];
    return ret;
}
void add(int u,ull v){
    e[cnt].v=v;
    e[cnt].nxt=head[u];
    head[u]=cnt++;
}
bool finds(ull x){
    int t=x%mod;
    for(int i=head[t];i!=-1;i=e[i].nxt){
        if(e[i].v==x) return true;
    }
    return 0;
}
bool check(int x){
    cnt=0;
    memset(head,-1,sizeof(head));
    for(int i=1;i+x-1<=n;i++){
        for(int j=1;j+x-1<=m;j++){
            ull t=cal(i,j,x);
            if(finds(t)) return true;
            add(t%mod,t);
        }
    }
    return 0;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    init();
    int l=1,r=min(n,m);
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
        else r=mid-1;
    }
    printf("%d\n",l-1);
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/zscoder/p/10658175.html