Matrix Matcher
题意:给两个二维字符串,问小的在大的里面出现了多少次。
本来看到白书上说ac自动机,搜题解看到有个人用hash写的,就学习了下。。。orz
等下再去敲自动机。。。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ull unsigned long long 4 #define CLR(m,a) memset(m,a,sizeof(m)) 5 const int maxn=1010; 6 ull base,seed=131,tpx[maxn][maxn],tpy[maxn][maxn],ans[maxn*maxn]; 7 int n,m; 8 9 char p[maxn][maxn],q[maxn][maxn]; 10 int Lfind(ull qsum) 11 { 12 int L=0,R=n*m-1; 13 int res=-1; 14 while(L<=R){ 15 int mid=L+(R-L)/2; 16 if(ans[mid]>=qsum){ 17 if(ans[mid]==qsum) res=mid; 18 R=mid-1; 19 } 20 else L=mid+1; 21 } 22 return res; 23 } 24 int Rfind(ull qsum) 25 { 26 int L=0,R=n*m-1; 27 int res=-1; 28 while(L<=R){ 29 int mid=L+(R-L)/2; 30 if(ans[mid]<=qsum){ 31 if(ans[mid]==qsum) res=mid; 32 L=mid+1; 33 } 34 else R=mid-1; 35 } 36 return res; 37 } 38 int main() 39 { 40 int t; 41 scanf("%d",&t); 42 while(t--){ 43 scanf("%d%d",&n,&m); 44 for(int i=0;i<n;i++) 45 scanf("%s",p[i]); 46 int x,y; 47 scanf("%d%d",&x,&y); 48 for(int i=0;i<x;i++) 49 scanf("%s",q[i]); 50 if(x>n||y>m){ 51 puts("0"); 52 continue; 53 } 54 CLR(tpx,0); 55 base=1; 56 for(int i=1;i<y;i++) base*=seed; 57 for(int i=0;i<n;i++){ 58 for(int j=0;j<y;j++) tpx[i][y-1]=tpx[i][y-1]*seed+p[i][j]; 59 for(int j=y;j<m;j++) tpx[i][j]=(tpx[i][j-1]-p[i][j-y]*base)*seed+p[i][j]; 60 } 61 CLR(tpy,0); 62 base=1; 63 for(int i=1;i<x;i++) base*=seed; 64 for(int i=0;i<m;i++){ 65 for(int j=0;j<x;j++) tpy[x-1][i]=tpy[x-1][i]*seed+tpx[j][i]; 66 for(int j=x;j<n;j++) tpy[j][i]=(tpy[j-1][i]-tpx[j-x][i]*base)*seed+tpx[j][i]; 67 } 68 int id=0; 69 for(int i=0;i<n;i++) 70 for(int j=0;j<m;j++) 71 ans[id++]=tpy[i][j]; 72 sort(ans,ans+id); 73 //求模板矩阵的哈希值 74 ull qsum=0; 75 for(int i=0;i<x;i++){ 76 ull temp=0; 77 for(int j=0;j<y;j++) temp=temp*seed+q[i][j]; 78 qsum=qsum*seed+temp; 79 } 80 if(Lfind(qsum)==-1){ 81 puts("0"); 82 continue; 83 } 84 printf("%d ",Rfind(qsum)-Lfind(qsum)+1); 85 } 86 return 0; 87 }