UVa 11019 Matrix Matcher - Hash
不会AC自动机做法。
考虑一维的字符串Hash怎么做。
对于一个长度为$l$的字符串$s$,它的Hash值$hash(s) = \sum_{i = 1}^{l}x^{l - i}s_{i}$。
对于二维的情况,我们就取两个基,$x, y$,对于一个$n\times m$的矩阵$A$的Hash值可以表示为
$hash(A) = \sum_{i = 1}^{n}\sum_{j = 1}^{m}x^{n - i}y^{m - j}a_{ij}$
然后以记录$S$的左上角的左上角的所有子矩阵的hash值(这个可以$O(1)$转移)。询问一个子矩阵的hash值,就可以$O(1)$回答。
接下来就很简单了。枚举每个位置判断是否匹配。
Code
1 /** 2 * UVa 3 * Problem#11019 4 * Accepted 5 * Time: 50ms 6 */ 7 #include <iostream> 8 #include <cstdlib> 9 #include <cstdio> 10 using namespace std; 11 typedef bool boolean; 12 13 const unsigned int hash1 = 200379, hash2 = 211985; 14 const int N = 1005, M = 105; 15 16 int p1[N], p2[N]; 17 int m, n, x, y; 18 char S[N][N], T[M][M]; 19 unsigned int hs[N][N]; 20 21 inline void prepare() { 22 p1[0] = 1, p2[0] = 1; 23 for (int i = 1; i < N; i++) 24 p1[i] = p1[i - 1] * hash1; 25 for (int i = 1; i < N; i++) 26 p2[i] = p2[i - 1] * hash2; 27 } 28 29 inline void init() { 30 scanf("%d%d", &n, &m); 31 for (int i = 1; i <= n; i++) 32 scanf("%s", S[i] + 1); 33 scanf("%d%d", &x, &y); 34 for (int i = 1; i <= x; i++) 35 scanf("%s", T[i] + 1); 36 } 37 38 inline void solve() { 39 for (int i = 1; i <= n; i++) 40 for (int j = 1; j <= m; j++) { 41 hs[i][j] = hs[i - 1][j - 1] * hash1 * hash2 + (hs[i - 1][j] - hs[i - 1][j - 1] * hash2) * hash1 + (hs[i][j - 1] - hs[i - 1][j - 1] * hash1) * hash2 + S[i][j]; 42 } 43 44 /* unsigned int s1 = 0; 45 for (int i = 1; i <= n; i++) 46 for (int j = 1; j <= m; j++) 47 s1 += S[i][j] * p1[n - i] * p2[m - j]; 48 49 cerr << s1 << " " << (97u * 200379 * 211985 + 98u * 200379 + 98u * 211985 + 97) << " " << hs[2][2] << endl;*/ 50 51 int rt = 0; 52 unsigned int s = 0, c; 53 for (int i = 1; i <= x; i++) 54 for (int j = 1; j <= y; j++) 55 s += T[i][j] * p1[x - i] * p2[y - j]; 56 // cerr << s << endl; 57 for (int i = x; i <= n; i++) 58 for (int j = y; j <= m; j++) { 59 c = hs[i][j] - hs[i - x][j - y] * p1[x] * p2[y] - (hs[i][j - y] - hs[i - x][j - y] * p1[x]) * p2[y] - (hs[i - x][j] - hs[i - x][j - y] * p2[y]) * p1[x]; 60 if (s == c) 61 rt++; 62 } 63 printf("%d\n", rt); 64 } 65 66 int kase; 67 int main() { 68 prepare(); 69 scanf("%d", &kase); 70 while (kase--) { 71 init(); 72 solve(); 73 } 74 return 0; 75 }