时间限制:1秒
空间限制:131072K
题目描述
给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。
输入描述:
第一行两个整数n, m代表矩阵的长和宽; 接下来n行,每行m个字符(小写字母),表示矩阵;
输出描述:
输出一个整数表示满足条件的最大正方形的边长。
示例1
输入
5 10 ljkfghdfas isdfjksiye pgljkijlgp eyisdafdsi lnpglkfkjl
输出
3
备注:
对于30%的数据,n,m≤100;对于100%的数据,n,m≤500;
这个和一维的差不多,坑点还是那个坑点,慎用map
代码:
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int maxn=600; int n,m; char a[maxn][maxn]; ull hashh[maxn][maxn],tmp[maxn][maxn]; inline void compute(int k) { const ull B1=9973; const ull B2=100000007; ull t1=1; for(int j=0; j<k; j++) t1*=B1; for(int i=0; i<n; i++) { ull e=0; for(int j=0; j<k; j++) e=e*B1+a[i][j]; for(int j=0; j+k<=m; j++) { tmp[i][j]=e; if(j+k<m) e=e*B1-t1*a[i][j]+a[i][j+k]; } } ull t2=1; for(int i=0; i<k; i++) { t2*=B2; } for(int j=0; j+k<=m; j++) { ull e=0; for(int i=0; i<k; i++) e=e*B2+tmp[i][j]; for(int i=0; i+k<=n; i++) { hashh[i][j]=e; if(i+k<n) e=e*B2-t2*tmp[i][j]+tmp[i+k][j]; } } } //map<ull,int>MAP; ull node[maxn*maxn]; inline int check(int x) { compute(x); int flag=0; int k=0; for(int i=0; i+x<=n; i++) for(int j=0; j+x<=m; j++) { node[k++]=hashh[i][j]; } sort(node,node+k); for(int i=1; i<k; i++) { if(node[i]==node[i-1]) { flag=1; break; } } return flag; } inline int minn(int x,int y) { if(x<y) return x; return y; } int main() { scanf("%d%d",&n,&m); int r=minn(n,m); int l=0; for(int i=0; i<n; i++) { scanf("%s",a[i]); } while(l<r) { int mid=(l+r+1)>>1; if(check(mid)) { l=mid; } else r=mid-1; } printf("%d\n",l); }