题干:
给出一个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代码:
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版)(这个时不时会跑个超时、。。)
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int>P;
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,,这次做题果然是,需要比较,所以需要先排序这样。