1. 程式人生 > >【字串二維hs】BZOJ 2462 BeiJing 2011 矩陣模板

【字串二維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
T

二維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 }