题意:给你一个零一矩阵,q次询问,每次给你两个长宽相同的子矩阵,问你它们是恰好有一位不同,还是完全相同,还是有多于一位不同。
对每行分别哈希,先一行一行地尝试匹配,如果恰好发现有一行无法对应,再对那一行内部进行暴力找出那一行内部有几位不同即可。
#include<cstdio> using namespace std; typedef unsigned long long ull; int n,m,q; char a[1005][1005]; ull b[1005][1005],pw[1005]; int sum[1005][1005]; //int Abs(int x){ // return x<0 ? (-x) : x; //} int calc(int x1,int y1,int x2,int y2){ return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]; } int main(){ //freopen("d.in","r",stdin); pw[0]=1; for(int i=1;i<=1001;++i){ pw[i]=pw[i-1]*(ull)233; } int l[5],r[5]; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%s",a[i]+1); } for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ sum[i][j]=sum[i-1][j]+a[i][j]-'0'; } } for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ sum[i][j]+=sum[i][j-1]; } } for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ b[i][j]=b[i][j-1]*(ull)233+(ull)(a[i][j]-'0'); } } scanf("%d",&q); for(;q;--q){ for(int j=1;j<=4;++j){ scanf("%d%d",&l[j],&r[j]); ++l[j]; ++r[j]; } // int t1=calc(l[1],r[1],l[2],r[2]); // int t2=calc(l[3],r[3],l[4],r[4]); // if(Abs(t1-t2)>1){ // puts("Wrong"); // continue; // } int kuan=r[2]-r[1]+1,cnt=0,I,J; for(int i=l[1],j=l[3];i<=l[2];++i,++j){ ull hs11=b[i][r[2]]-(b[i][r[1]-1]*pw[kuan]); ull hs21=b[j][r[4]]-(b[j][r[3]-1]*pw[kuan]); if(!(hs11==hs21)){ ++cnt; I=i; J=j; if(cnt>1){ break; } } } if(cnt>1){ puts("Wrong"); continue; } else if(cnt==0){ puts("Perfect"); continue; } cnt=0; for(int k1=r[1],k2=r[3];k1<=r[2];++k1,++k2){ if(a[I][k1]!=a[J][k2]){ ++cnt; if(cnt>1){ break; } } } if(cnt>1){ puts("Wrong"); } else{ puts("One difference"); } } return 0; }