二维hash出错求查
查看原帖
二维hash出错求查
81298
VLMOESR楼主2021/1/25 20:33

样例过了,我是枚举右下角的点,向上边和左边拓展

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int n, m;
unsigned long long a[1010][1010], b[1010][1010], c[1010][1010];
unsigned long long f[1010], f2[1010];
bool check(int x, int y, int len)
{
	if(x-len<0||y-len<0)
		return 0;
	int res1=a[x][y]-a[x-len][y]*f[len]-a[x][y-len]*f2[len]+a[x-len][y-len]*f[len]*f2[len];
    int yy=m-(y-len);
    int res2=b[x][yy]-b[x-len][yy]*f[len]-b[x][yy-len]*f2[len]+b[x-len][yy-len]*f[len]*f2[len];
    int xx=n-(x-len);
    int res3=c[xx][y]-c[xx-len][y]*f[len]-c[xx][y-len]*f2[len]+c[xx-len][y-len]*f[len]*f2[len];
	if(res1==res2&&res2==res3)
		return 1;
	else
		return 0;
} 
void hs()
{
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
		{
			a[i][j]=a[i][j-1]*13331ull+a[i][j];
			b[i][j]=b[i][j-1]*13331ull+b[i][j];
			c[i][j]=c[i][j-1]*13331ull+c[i][j];
		}
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
		{
			a[i][j]+=a[i-1][j]*13331ull;
			b[i][j]+=b[i-1][j]*13331ull;
			c[i][j]+=c[i-1][j]*13331ull;
		}
	f[0]=1ull;
	for(int i=1; i<=n; i++)
		f[i]=f[i-1]*13331ull;
	f2[0]=1ull;
	for(int i=1; i<=m; i++)
		f2[i]=f2[i-1]*13331ull;
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
		{
			scanf("%d", &a[i][j]);
			b[i][m-j+1]=a[i][j];
			c[n-i+1][j]=a[i][j];
		}
	hs();
	int ans=0;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
		{
			int l=0, r=min(n, m), maxx=1;
			while(l<=r)
			{
				int mid=l+r>>1;
				if(check(i, j, mid))
					maxx=max(maxx, mid+1), l=mid+1;
				else
					r=mid-1;
			}
				ans+=(maxx+1)/2; 
		}
	printf("%d", ans);
	return 0;
}
/*
5 5
4 2 4 4 4
3 1 4 4 3
3 5 3 3 3
3 1 5 3 3
4 2 1 2 4
*/
2021/1/25 20:33
加载中...