1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
using u64 = unsigned long long;
static inline u64 cellValue(char ch) {
return ch == 'o' ? 1ULL : 2ULL; // 'o'와 'x'를 서로 다른 값으로 매핑
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int hp, wp, hm, wm;
if (!(cin >> hp >> wp >> hm >> wm)) return 0;
vector<string> P(hp), M(hm);
for (int i = 0; i < hp; ++i) cin >> P[i];
for (int i = 0; i < hm; ++i) cin >> M[i];
// 2D Rolling Hash with double 64-bit bases (wrap-around modulo 2^64)
const u64 BASE_COL_A = 146527ULL;
const u64 BASE_ROW_A = 19260817ULL;
const u64 BASE_COL_B = 911382323ULL;
const u64 BASE_ROW_B = 972663749ULL;
// Precompute powers
vector<u64> powColA(wm + 1, 1), powRowA(hm + 1, 1);
vector<u64> powColB(wm + 1, 1), powRowB(hm + 1, 1);
for (int i = 1; i <= wm; ++i) {
powColA[i] = powColA[i - 1] * BASE_COL_A;
powColB[i] = powColB[i - 1] * BASE_COL_B;
}
for (int i = 1; i <= hm; ++i) {
powRowA[i] = powRowA[i - 1] * BASE_ROW_A;
powRowB[i] = powRowB[i - 1] * BASE_ROW_B;
}
// Pattern hash
u64 patRowA, patRowB;
vector<u64> patRowsA(hp), patRowsB(hp);
for (int r = 0; r < hp; ++r) {
u64 hA = 0, hB = 0;
for (int c = 0; c < wp; ++c) {
u64 v = cellValue(P[r][c]);
hA = hA * BASE_COL_A + v;
hB = hB * BASE_COL_B + v;
}
patRowsA[r] = hA;
patRowsB[r] = hB;
}
u64 patA = 0, patB = 0;
for (int r = 0; r < hp; ++r) {
patA = patA * BASE_ROW_A + patRowsA[r];
patB = patB * BASE_ROW_B + patRowsB[r];
}
// Row-wise rolling hashes for the masterpiece (width = wp)
const int W = wm - wp + 1;
const int H = hm - hp + 1;
vector<vector<u64>> rowA(hm, vector<u64>(max(0, W)));
vector<vector<u64>> rowB(hm, vector<u64>(max(0, W)));
if (W <= 0 || H <= 0) {
cout << 0 << '\n';
return 0;
}
for (int i = 0; i < hm; ++i) {
u64 hA = 0, hB = 0;
for (int c = 0; c < wp; ++c) {
u64 v = cellValue(M[i][c]);
hA = hA * BASE_COL_A + v;
hB = hB * BASE_COL_B + v;
}
rowA[i][0] = hA;
rowB[i][0] = hB;
for (int j = 1; j < W; ++j) {
u64 vOut = cellValue(M[i][j - 1]);
u64 vIn = cellValue(M[i][j + wp - 1]);
hA = hA * BASE_COL_A + vIn - powColA[wp] * vOut;
hB = hB * BASE_COL_B + vIn - powColB[wp] * vOut;
rowA[i][j] = hA;
rowB[i][j] = hB;
}
}
// Vertical rolling for each column window
long long answer = 0;
for (int j = 0; j < W; ++j) {
u64 vA = 0, vB = 0;
for (int i = 0; i < hp; ++i) {
vA = vA * BASE_ROW_A + rowA[i][j];
vB = vB * BASE_ROW_B + rowB[i][j];
}
if (vA == patA && vB == patB) ++answer;
for (int i = 1; i < H; ++i) {
u64 outA = rowA[i - 1][j], inA = rowA[i + hp - 1][j];
u64 outB = rowB[i - 1][j], inB = rowB[i + hp - 1][j];
vA = vA * BASE_ROW_A + inA - powRowA[hp] * outA;
vB = vB * BASE_ROW_B + inB - powRowB[hp] * outB;
if (vA == patA && vB == patB) ++answer;
}
}
cout << answer << '\n';
return 0;
}
|