题干:
给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。
输入描述:
第一行两个整数n, m代表矩阵的长和宽;
接下来n行,每行m个字符(小写字母),表示矩阵;
输出描述:
输出一个整数表示满足条件的最大正方形的边长。
示例1
输入
5 10
ljkfghdfas
isdfjksiye
pgljkijlgp
eyisdafdsi
lnpglkfkjl
输出
3
备注:
对于30%的数据,n,m≤100;
对于100%的数据,n,m≤500;
解题报告:
非常恶心的字符串Hash,,琢磨了半天才看明白、、这种前缀的是需要去模数的
AC代码:
//#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;
//}
#include<cstdio>
#include<algorithm>
#define N 510
using namespace std;
typedef unsigned long long ll;
const ll D1=97,D2=131;
int n,m,i,j,l,r,mid,ans,t;
char a[N][N];
ll pow1[N],pow2[N],h[N][N],tmp,Hash[N*N];
bool check(int x) {
for(i=1; i<=n; i++) {
for(tmp=0,j=1; j<x; j++) tmp=tmp*D1+a[i][j],h[i][j]=0;
for(j=x; j<=m; j++) h[i][j]=tmp=tmp*D1-pow1[x]*a[i][j-x]+a[i][j];
}
for(t=0,i=x; i<=m; i++) {
for(tmp=0,j=1; j<x; j++) tmp=tmp*D2+h[j][i];
for(j=x; j<=n; j++) Hash[t++]=tmp=tmp*D2-pow2[x]*h[j-x][i]+h[j][i];
}
sort(Hash,Hash+t);
for(i=1; i<t; i++) {
if(Hash[i-1]==Hash[i])return 1;
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++) {
scanf("%s",a[i]+1);
for(j=1; j<=m; j++) {
a[i][j]-='a';
}
}
l=1,r=min(n,m);
pow1[0]=pow2[0]=1;
for(i=1; i<=n; i++) pow1[i]=pow1[i-1]*D1;
for(i=1; i<=m; i++) pow2[i]=pow2[i-1]*D2;
while(l<=r) {
mid=(l+r)>>1;
if(check(mid)) l=mid+1,ans=mid;
else r=mid-1;
}
printf("%d",ans);
return 0;
}