【字符串二维hs】BZOJ 2462 BeiJing 2011 矩阵模板
2462: [BeiJing2011]矩阵模板 Time Limit: 2 Sec Memory Limit: 128 MB Submit: 1929 Solved: 820 [Submit][Status][Discuss] Description 给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在 原矩阵中出现过。 所谓01矩阵,就是矩阵中所有元素不是0就是1。 Input 输入文件的第一行为M、N、A、B,参见题目描述。 接下来M行,每行N个字符,非0即1,描述原矩阵。 接下来一行为你要处理的询问数Q。 接下来Q个矩阵,一共Q*A行,每行B个字符,描述Q个01矩阵。 Output 你需要输出Q行,每行为0或者1,表示这个矩阵是否出现过,0表示没有出现过,1表 示出现过。 Sample Input 3 3 2 2 111 000 111 3 11 00 11 11 00 11 Sample Output 1 0 1 HINT 对于100%的数据,N,M<=1000 A,B<=100 Source Day4
二维hs就是横着一个seed,纵着一个seed,然后合并查询和矩阵前缀和没有区别,十分easy
注意n和m不要弄混了
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 1111 5 #define p 13131 6 #define q 1313131 7 #define ull unsigned long long 8 using namespace std; 9 int n,m,a,b,qq; 10 ull hs[N][N],tt[N][N],sep[N],seq[N]; 11 char in[N][N],ques[150][150]; 12 inline ull geths(int l1,int l2,int r1,int r2) 13 {return hs[r2][l2]-hs[r2][l1-1]*seq[b]-hs[r1-1][l2]*sep[a]+hs[r1-1][l1-1]*sep[a]*seq[b];} 14 int main() 15 { 16 scanf("%d%d%d%d",&n,&m,&a,&b); 17 sep[0]=seq[0]=1; 18 for(int i=1;i<N;i++)sep[i]=sep[i-1]*p,seq[i]=seq[i-1]*q; 19 for(int i=1;i<=m;i++) 20 scanf("%s",in[i]+1); 21 for(int i=1;i<=m;i++) 22 for(int j=1;j<=n;j++) 23 hs[i][j]=hs[i-1][j]*p+hs[i][j-1]*q-hs[i-1][j-1]*p*q+in[i][j]; 24 scanf("%d",&qq); 25 for(int que=1;que<=qq;que++) 26 { 27 for(int i=1;i<=a;i++) 28 scanf("%s",ques[i]+1); 29 memset(tt,0,sizeof(tt)); 30 for(int i=1;i<=a;i++) 31 for(int j=1;j<=b;j++) 32 tt[i][j]=tt[i-1][j]*p+tt[i][j-1]*q-tt[i-1][j-1]*p*q+ques[i][j]; 33 ull val=tt[a][b]; 34 bool fl=0; 35 for(int l1=1;l1+b-1<=n;l1++) 36 { 37 int l2=l1+b-1; 38 for(int r1=1;r1+a-1<=m;r1++) 39 { 40 int r2=r1+a-1; 41 if(geths(l1,l2,r1,r2)==val) 42 {fl=1;break;} 43 } 44 if(fl)break; 45 } 46 if(fl)printf("1\n"); 47 else printf("0\n"); 48 } 49 return 0; 50 }