题意:给出一个N*M的矩阵和一个X*Y的模板矩阵,求模板矩阵在矩阵中的出现次数。
思路:
二维哈希。
类似于求前缀和,假设纵向的base是base1,横向的的base是base2 。
预处理:
hash[i][j]=(s[i][j]-'a'+1)
+hash[i-1][j]*base1
+hash[i][j-1]*base2
-hash[i-1][j-1]*base1*base2
basex=base1^x
basey=base2^y
右下角为[i,j],大小为X*Y的区域哈希值:
hash[i][j]
-hash[i-x][j]*basex
-hash[i][j-y]*basey
+hash[i-x][j-y]*basex*basey
AC代码:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 typedef unsigned long long ull; 5 6 const ull base1=107,base2=131; 7 8 char s1[1000+10][1000+10],s2[100+10][100+10]; 9 ull hash1[1000+10][1000+10],hash2[100+10][100+10]; 10 ull basex,basey; 11 int n,m,x,y; 12 13 int main() 14 { 15 int T;scanf("%d",&T); 16 while(T--){ 17 scanf("%d%d",&n,&m); 18 for (int i=1;i<=n;i++) scanf("%s",s1[i]+1); 19 20 scanf("%d%d",&x,&y); 21 for (int i=1;i<=x;i++) scanf("%s",s2[i]+1); 22 23 for (int i=1;i<=n;i++) 24 for (int j=1;j<=m;j++) 25 hash1[i][j]=(s1[i][j]-'a'+1)+hash1[i-1][j]*base1+hash1[i][j-1]*base2-hash1[i-1][j-1]*base1*base2; 26 27 for (int i=1;i<=x;i++) 28 for (int j=1;j<=y;j++) 29 hash2[i][j]=(s2[i][j]-'a'+1)+hash2[i-1][j]*base1+hash2[i][j-1]*base2-hash2[i-1][j-1]*base1*base2; 30 31 basex=1,basey=1; 32 for (int i=1;i<=x;i++) basex=basex*base1; 33 for (int i=1;i<=y;i++) basey=basey*base2; 34 35 int ans=0; 36 for (int i=x;i<=n;i++) 37 for (int j=y;j<=m;j++) 38 if (hash2[x][y]==hash1[i][j]-hash1[i-x][j]*basex-hash1[i][j-y]*basey+hash1[i-x][j-y]*basex*basey) 39 ans++; 40 41 printf("%d\n",ans); 42 } 43 return 0; 44 }