#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;
}
}