0
点赞
收藏
分享

微信扫一扫

*【牛客 1 - A】矩阵(字符串hash)

q松_松q 2022-06-15 阅读 88

题干:
 

给出一个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) {
t=0;
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;
}

AC代码3:(还是这种二维Hash看得懂一点)

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn=2e6+10;
const ull base1=131,base2=233; //base,基数

int n, m;
char mp[510][510];
ull has[510][510];
ull p1[510], p2[510];
map<ull, int> mmp;

void init()
{
p1[0] = p2[0] = 1;
for(int i = 1; i <= 505; i ++)
{
p1[i] = p1[i-1]*base1;
p2[i] = p2[i-1]*base2;
}
}

void Hash()
{
has[0][0] = 0;
has[0][1] = 0;
has[1][0] = 0;
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m; j ++)
{
has[i][j] = has[i][j-1]*base1 + mp[i][j] - 'a';
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j ++)
{
has[i][j] = has[i-1][j]*base2 + has[i][j];
}
}
}

bool check(int x)
{
mmp.clear();
for(int i = x; i <= n; i ++)
{
for(int j = x; j <= m; j ++)
{
ull k = has[i][j] - has[i-x][j]*p2[x] - has[i][j-x]*p1[x] + has[i-x][j-x]*p1[x]*p2[x];
mmp[k] ++;
if(mmp[k] >= 2)
return true;
}
}
return false;
}

int main()
{
init();
while(~scanf("%d%d", &n, &m))
{
for(int i = 1; i <= n; i ++)
{
scanf("%s", mp[i]+1);
}
Hash();
int l = 0, r = 600, ans = 0;
while(l <= r)
{
int mid = (l+r)/2;
if(check(mid))
{
l = mid+1;
ans = mid;
}
else
{
r = mid-1;
}
}
printf("%d\n", ans);
}
return 0;
}

 


举报

相关推荐

0 条评论