제출 #1363673

#제출 시각아이디문제언어결과실행 시간메모리
1363673vjudge1Sateliti (COCI20_satellti)C++17
110 / 110
455 ms38752 KiB
#include <bits/stdc++.h>
using namespace std;

// Include Hash2D struct here
#include <bits/stdc++.h>
using namespace std;

struct Hash2D {
	static const int mod1 = 1e9 + 7, mod2 = 1e9 + 9;
	static const int base_row = 91138233;
	static const int base_col = 97266353;

	int n, m;
	vector<vector<pair<int, int>>> H;  // 1-indexed
	vector<int> pow_row1, pow_row2, pow_col1, pow_col2;

	Hash2D(const vector<string>& g) {
		n = g.size();
		m = g[0].size();

		pow_row1.resize(m + 1, 1);
		pow_row2.resize(m + 1, 1);
		pow_col1.resize(n + 1, 1);
		pow_col2.resize(n + 1, 1);

		for (int i = 1; i <= m; i++) {
			pow_row1[i] = 1LL * pow_row1[i - 1] * base_row % mod1;
			pow_row2[i] = 1LL * pow_row2[i - 1] * base_row % mod2;
		}

		for (int i = 1; i <= n; i++) {
			pow_col1[i] = 1LL * pow_col1[i - 1] * base_col % mod1;
			pow_col2[i] = 1LL * pow_col2[i - 1] * base_col % mod2;
		}

		H.assign(n + 1, vector<pair<int, int>>(m + 1, {0, 0}));

		for (int i = 1; i <= n; i++) {
			int row1 = 0, row2 = 0;
			for (int j = 1; j <= m; j++) {
				int val = g[i - 1][j - 1];

				// 1D row hash
				row1 = (1LL * row1 * base_row + val) % mod1;
				row2 = (1LL * row2 * base_row + val) % mod2;

				// combine vertically
				H[i][j].first =
					(1LL * H[i - 1][j].first * base_col + row1) % mod1;

				H[i][j].second =
					(1LL * H[i - 1][j].second * base_col + row2) % mod2;
			}
		}
	}

	// get hash of submatrix [x1..x2][y1..y2] (1-indexed)
	pair<int, int> get(int x1, int y1, int x2, int y2) {
		int h1 = H[x2][y2].first;
		int h2 = H[x2][y2].second;

		// remove upper part
		h1 = (h1 - 1LL * H[x1 - 1][y2].first * pow_col1[x2 - x1 + 1] % mod1 +
			  mod1) %
			 mod1;
		h2 = (h2 - 1LL * H[x1 - 1][y2].second * pow_col2[x2 - x1 + 1] % mod2 +
			  mod2) %
			 mod2;

		// remove left part
		h1 = (h1 - 1LL * H[x2][y1 - 1].first * pow_row1[y2 - y1 + 1] % mod1 +
			  mod1) %
			 mod1;
		h2 = (h2 - 1LL * H[x2][y1 - 1].second * pow_row2[y2 - y1 + 1] % mod2 +
			  mod2) %
			 mod2;

		// add overlap
		h1 = (h1 +
			  1LL * H[x1 - 1][y1 - 1].first *
				  (1LL * pow_col1[x2 - x1 + 1] * pow_row1[y2 - y1 + 1] % mod1) %
				  mod1) %
			 mod1;

		h2 = (h2 +
			  1LL * H[x1 - 1][y1 - 1].second *
				  (1LL * pow_col2[x2 - x1 + 1] * pow_row2[y2 - y1 + 1] % mod2) %
				  mod2) %
			 mod2;

		return {h1, h2};
	}
};

int main() {
	int n, m;
	cin >> n >> m;

	vector<string> original(n);
	for (int i = 0; i < n; i++) {
		cin >> original[i];
	}
	vector<string> grid(2 * n, string(2 * m, ' '));
	for (int i = 0; i < 2 * n; i++) {
		for (int j = 0; j < 2 * m; j++) {
			grid[i][j] = original[i % n][j % m];
		}
	}
	Hash2D hs(grid);
	pair<int, int> best = {0, 0};
	for (int i = 0; i < n; i++) {
		auto& [xx, yy] = best;
		for (int j = 0; j < m; j++) {
			auto cur = hs.get(i + 1, j + 1, i + n, j + m);
			auto bst = hs.get(xx + 1, yy + 1, xx + n, yy + m);
			if (bst == cur) continue;
			int lrow = 1, rrow = n, bstrow = 0;
			while (lrow <= rrow) {
				int mid = (lrow + rrow >> 1);
				auto precur = hs.get(i + 1, j + 1, i + mid, j + m);
				auto prebst = hs.get(xx + 1, yy + 1, xx + mid, yy + m);
				if (precur == prebst) {
					lrow = mid + 1;
				} else {
					rrow = mid - 1;
					bstrow = mid;
				}
			}
			int lcol = 1, rcol = m, bstcol = 0;
			while (lcol <= rcol) {
				int mid = (lcol + rcol >> 1);
				auto precur = hs.get(i + bstrow, j + 1, i + bstrow, j + mid);
				auto prebst =
					hs.get(xx + bstrow, yy + 1, xx + bstrow, yy + mid);
				if (precur == prebst) {
					lcol = mid + 1;
				} else {
					rcol = mid - 1;
					bstcol = mid;
				}
			}
			if (grid[i + bstrow - 1][j + bstcol - 1] <
				grid[xx + bstrow - 1][yy + bstcol - 1])
				best = {i, j};
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cout << grid[best.first + i][best.second + j];
		}
		cout << endl;
	}
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…