1. 程式人生 > >UVa 11019 Matrix Matcher - Hash

UVa 11019 Matrix Matcher - Hash

target 快速 傳送門 ng- main option col cst ron

題目傳送門

  快速的vjudge傳送門

  快速的UVa傳送門

題目大意

  給定兩個矩陣S和T,問T在S中出現了多少次。

  不會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 }

UVa 11019 Matrix Matcher - Hash