题干:

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

输入描述:

第一行两个整数n, m代表矩阵的长和宽;
接下来n行,每行m个字符(小写字母),表示矩阵;

输出描述:

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

 

示例1

输入

复制

5 10
ljkfghdfas
isdfjksiye
pgljkijlgp
eyisdafdsi
lnpglkfkjl

输出

复制

3

备注:

对于30%的数据,n,m≤100;
对于100%的数据,n,m≤500;

解题报告:

   二分一下矩阵的边长,然后用字符串哈希判断两个矩阵是否相同就可以,,网络上找到一个map的解法,,但是感觉时间复杂度太不稳定,好的时候700ms,差的时候超时,,于是还是以后用多项式哈希吧。。这两个刚学哈希,,代码还是不特别美观、、

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 505;
using namespace std;
const ll D1=31,D2=131;
int n,m;
char a[MAX][MAX];
ull pow1[MAX],pow2[MAX],h[MAX][MAX],tmp,tmp2,Hash[MAX*MAX];
bool ok(int x) {
memset(h,0,sizeof h);
int tot=0;
for(int i = 1; i<=n; i++) {
ull tmp = 0;
for(int j = 1; j<x; j++) h[i][j] = h[i][j-1] * D1 + a[i][j];
for(int j = x; j<=m; j++) h[i][j] = h[i][j-1] * D1 + a[i][j] - pow1[x] * a[i][j-x];
// for(int j = 1; j<x; j++) tmp = tmp * D1 + a[i][j];
// for(int j = x; j<=m; j++) h[i][j] = tmp * D1 + a[i][j] - pow1[x] * a[i][j-x] , tmp = h[i][j];
}
for(int j = x; j<=m; j++) {
ull tmp = 0;
for(int i = 1; i<x; i++) tmp = tmp*D2 + h[i][j];
for(int i = x; i<=n; i++) Hash[++tot] = tmp*D2 + h[i][j] - pow2[x] * h[i-x][j] , tmp = Hash[tot];
}
sort(Hash+1,Hash+tot+1);
for(int i = 1; i<tot; i++) {
if(Hash[i] == Hash[i+1]) return 1;
}
return 0 ;
}
int main()
{
// ull qq=1,ww=2;
// cout <<qq-ww;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) {
scanf("%s",a[i]+1);
for(int j=1; j<=m; j++) {
a[i][j]-=('a'-1);
}
}
int l=1,r=min(n,m);
int mid = (l+r)>>1;
int ans;
pow1[0]=pow2[0]=1;
for(int i=1; i<=n; i++) pow1[i]=pow1[i-1]*D1;
for(int i=1; i<=m; i++) pow2[i]=pow2[i-1]*D2;
while(l<=r) {
mid=(l+r)>>1;
if(ok(mid)) l=mid+1,ans=mid;
else r=mid-1;
}

printf("%d",ans);
return 0;
}

AC代码2:(map版)(这个时不时会跑个超时、。。)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int>P;
#define maxn 505
int n,m;
char s[maxn][maxn];
ull h[maxn][maxn],b[maxn*maxn],base=10007,hhh[maxn][maxn];
inline int ID(int i,int j) {
return (i-1)*m+j;
}
inline bool check(int mid) {
map<ull,int>M;
for(int x=1; x<=n-mid+1; x++)
for(int y=1; y<=m-mid+1; y++) {
int xx=x+mid-1,yy=y+mid-1;
ull val=(h[xx][yy]-h[xx][y-1]-h[x-1][yy]+h[x-1][y-1])*b[(n-x)*m+m-y];
if(M.find(val)!=M.end())return 1;
M[val]=1;
}
return 0;
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)scanf("%s",s[i]+1);
b[0]=1;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++) {
h[i][j]=h[i][j-1]+b[ID(i,j-1)]*(s[i][j]-'a');
b[ID(i,j)]=b[ID(i,j-1)]*base;
}
// for(int j=1; j<=m; j++)
// for(int i=1; i<=n; i++)
// h[i][j]+=h[i-1][j];
int l=0,r=min(n,m),mid,ans=0;
while(l<=r) {
mid=(l+r)/2;
if(check(mid))ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}

总结:据syt表示,哈希题目多半带个log,,这次做题果然是,需要比较,所以需要先排序这样。