题目
给出一个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; }