#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_14_C" #include <iostream> #include <string> #include <vector> #include "Mylib/IO/input_vector.cpp" #include "Mylib/String/rolling_hash_2d.cpp" namespace hl = haar_lib; int main() { auto rh = hl::make_rh_2d(1000, 1000, 1000000007); int H, W; std::cin >> H >> W; auto s = hl::input_vector<std::string>(H); int R, C; std::cin >> R >> C; auto t = hl::input_vector<std::string>(R); auto res = rh.find(s, t); for (auto [i, j] : res) std::cout << i << " " << j << "\n"; return 0; }
#line 1 "test/aoj/ALDS1_14_C/main.test.cpp" #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_14_C" #include <iostream> #include <string> #include <vector> #line 4 "Mylib/IO/input_vector.cpp" namespace haar_lib { template <typename T> std::vector<T> input_vector(int N) { std::vector<T> ret(N); for (int i = 0; i < N; ++i) std::cin >> ret[i]; return ret; } template <typename T> std::vector<std::vector<T>> input_vector(int N, int M) { std::vector<std::vector<T>> ret(N); for (int i = 0; i < N; ++i) ret[i] = input_vector<T>(M); return ret; } } // namespace haar_lib #line 2 "Mylib/String/rolling_hash_2d.cpp" #include <random> #line 4 "Mylib/String/rolling_hash_2d.cpp" namespace haar_lib { class rolling_hash_2d { std::vector<int64_t> pow_w_, pow_h_; int64_t MOD_, BASEW_, BASEH_; public: rolling_hash_2d() {} rolling_hash_2d(int width, int height, int MOD, int BASEW, int BASEH) : MOD_(MOD), BASEW_(BASEW), BASEH_(BASEH) { pow_w_.resize(width + 1); pow_h_.resize(height + 1); pow_w_[0] = pow_h_[0] = 1; for (int i = 1; i <= width; ++i) pow_w_[i] = pow_w_[i - 1] * BASEW_ % MOD_; for (int i = 1; i <= height; ++i) pow_h_[i] = pow_h_[i - 1] * BASEH_ % MOD_; } template <typename T> auto gen_hash_table(const T &s) const { const int n = s.size(), m = s[0].size(); std::vector<std::vector<int64_t>> ret(n + 1, std::vector<int64_t>(m + 1)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { ret[i + 1][j + 1] = (ret[i + 1][j] * BASEW_ + s[i][j]) % MOD_; } } for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { ret[i + 1][j + 1] = (ret[i][j + 1] * BASEH_ + ret[i + 1][j + 1]) % MOD_; } } return ret; } template <typename T> auto gen_hash(const T &s) const { const int n = s.size(), m = s[0].size(); int64_t ret = 0; for (int i = 0; i < n; ++i) { int64_t temp = 0; for (int j = 0; j < m; ++j) { temp = (temp * BASEW_ + s[i][j]) % MOD_; } ret = (ret * BASEH_ + temp) % MOD_; } return ret; } /** * @attention [i1, i2), [j1, j2) */ int64_t get(const std::vector<std::vector<int64_t>> &table, int i1, int j1, int i2, int j2) const { const auto a = table[i2][j2]; const auto b = table[i1][j2] * pow_h_[i2 - i1] % MOD_; const auto c = table[i2][j1] * pow_w_[j2 - j1] % MOD_; const auto d = table[i1][j1] * pow_h_[i2 - i1] % MOD_ * pow_w_[j2 - j1] % MOD_; return (((a - b + MOD_) % MOD_ - c + MOD_) % MOD_ + d + MOD_) % MOD_; } template <typename T> std::vector<std::pair<int, int>> find(const T &s, const T &pattern) const { auto hp = gen_hash(pattern); auto hs = gen_hash_table(s); const int H = s.size(); const int W = s[0].size(); const int R = pattern.size(); const int C = pattern[0].size(); std::vector<std::pair<int, int>> ret; for (int i = 0; i <= H - R; ++i) { for (int j = 0; j <= W - C; ++j) { if (hp == get(hs, i, j, i + R, j + C)) ret.emplace_back(i, j); } } return ret; } }; auto make_rh_2d(int width, int height, int MOD, int seed = 0) { std::mt19937 rnd(seed); std::uniform_int_distribution<> dist(2, MOD - 2); return rolling_hash_2d(width, height, MOD, dist(rnd), dist(rnd)); } } // namespace haar_lib #line 8 "test/aoj/ALDS1_14_C/main.test.cpp" namespace hl = haar_lib; int main() { auto rh = hl::make_rh_2d(1000, 1000, 1000000007); int H, W; std::cin >> H >> W; auto s = hl::input_vector<std::string>(H); int R, C; std::cin >> R >> C; auto t = hl::input_vector<std::string>(R); auto res = rh.find(s, t); for (auto [i, j] : res) std::cout << i << " " << j << "\n"; return 0; }