Поиск одинаковых подматриц в матрице символов
mod = 10**9 + 7
p, q = 31, 57
def add(a, b):
if a + b >= mod:
return a + b - mod
return a + b
def sub(a, b):
if a - b < 0:
return a - b + mod
return a - b
def mul(a, b):
return a * b % mod
n, k = map(int, input().split())
A = [input() for _ in range(n)]
H = [[0] * (k + 1) for _ in range(n + 1)]
PU = [[0] * (k + 1) for _ in range(n + 1)]
PV = [[0] * (k + 1) for _ in range(n + 1)]
for i in range(n + 1):
for j in range(k + 1):
if i == 0 and j == 0:
PU[i][j] = PV[i][j] = 1
elif j == 0:
PU[i][j] = 1
PV[i][j] = mul(PV[i - 1][j], q)
elif i == 0:
PV[i][j] = 1
PU[i][j] = mul(PU[i][j - 1], p)
else:
PU[i][j] = mul(PU[i][j - 1], p)
PV[i][j] = mul(PV[i - 1][j], q)
for i in range(n):
for j in range(k):
x = ord(A[i][j]) - ord('a') + 1
H[i + 1][j + 1] = add(H[i + 1][j + 1], x)
H[i + 1][j + 1] = add(H[i + 1][j + 1], mul(H[i + 1][j], p))
H[i + 1][j + 1] = add(H[i + 1][j + 1], mul(H[i][j + 1], q))
H[i + 1][j + 1] = sub(H[i + 1][j + 1], mul(mul(H[i][j], p), q))
def func(x1, y1, x2, y2):
a = x2 - x1 + 1
b = y2 - y1 + 1
h0 = H[x2 + 1][y2 + 1]
h1 = mul(H[x2 + 1][y1], PU[a][b])
h2 = mul(H[x1][y2 + 1], PV[a][b])
h3 = mul(H[x1][y1], mul(PU[a][b], PV[a][b]))
h = sub(sub(h0, h1), h2)
h = add(h, h3)
return h
def ok(m):
D = dict()
for i in range(n - m + 1):
for j in range(k - m + 1):
h = func(i, j, i + m - 1, j + m - 1)
if h in D:
i1, j1 = D[h]
return True, i, j, i1, j1
else:
D[h] = (i, j)
return False, -1, -1, -1, -1
l, r = 0, n + 1
while l < r - 1:
m = (l + r) // 2
f, _, _, _, _ = ok(m)
if f:
l = m
else:
r = m
f, x1, y1, x2, y2 = ok(l)
if l == 0:
print(0)
else:
print(l)
print(x1 + 1, y1 + 1)
print(x2 + 1, y2 + 1)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1000000007;
const ll p = 31, q = 57;
ll add(ll a, ll b) {
if (a + b >= mod) return a + b - mod;
return a + b;
}
ll sub(ll a, ll b) {
if (a - b < 0) return a - b + mod;
return a - b;
}
ll mul(ll a, ll b) {
return a * b % mod;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, k;
cin >> n >> k;
vector<string> A(n);
for (int i = 0; i < n; i++) {
cin >> A[i];
}
vector<vector<ll>> H(n + 1, vector<ll>(k + 1, 0));
vector<vector<ll>> PU(n + 1, vector<ll>(k + 1, 0));
vector<vector<ll>> PV(n + 1, vector<ll>(k + 1, 0));
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= k; j++) {
if (i == 0 && j == 0) {
PU[i][j] = PV[i][j] = 1;
} else if (j == 0) {
PU[i][j] = 1;
PV[i][j] = mul(PV[i - 1][j], q);
} else if (i == 0) {
PV[i][j] = 1;
PU[i][j] = mul(PU[i][j - 1], p);
} else {
PU[i][j] = mul(PU[i][j - 1], p);
PV[i][j] = mul(PV[i - 1][j], q);
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
ll x = A[i][j] - 'a' + 1;
H[i + 1][j + 1] = add(H[i + 1][j + 1], x);
H[i + 1][j + 1] = add(H[i + 1][j + 1], mul(H[i + 1][j], p));
H[i + 1][j + 1] = add(H[i + 1][j + 1], mul(H[i][j + 1], q));
H[i + 1][j + 1] = sub(H[i + 1][j + 1], mul(mul(H[i][j], p), q));
}
}
auto func = [&](int x1, int y1, int x2, int y2) {
int a = x2 - x1 + 1;
int b = y2 - y1 + 1;
ll h0 = H[x2 + 1][y2 + 1];
ll h1 = mul(H[x2 + 1][y1], PU[a][b]);
ll h2 = mul(H[x1][y2 + 1], PV[a][b]);
ll h3 = mul(H[x1][y1], mul(PU[a][b], PV[a][b]));
ll h = sub(sub(h0, h1), h2);
h = add(h, h3);
return h;
};
auto ok = [&](int m) -> tuple<bool, int, int, int, int> {
unordered_map<ll, pair<int, int>> D;
for (int i = 0; i < n - m + 1; i++) {
for (int j = 0; j < k - m + 1; j++) {
ll h = func(i, j, i + m - 1, j + m - 1);
auto it = D.find(h);
if (it != D.end()) {
auto [i1, j1] = it->second;
return {true, i, j, i1, j1};
} else {
D[h] = {i, j};
}
}
}
return {false, -1, -1, -1, -1};
};
int l = 0, r = n + 1;
while (l < r - 1) {
int m = (l + r) / 2;
auto [f, _, __, ___, ____] = ok(m);
if (f) l = m;
else r = m;
}
auto [f, x1, y1, x2, y2] = ok(l);
if (l == 0) {
cout << 0 << "\n";
} else {
cout << l << "\n";
cout << x1 + 1 << " " << y1 + 1 << "\n";
cout << x2 + 1 << " " << y2 + 1 << "\n";
}
return 0;
}
Двумерное хеширование — это метод, который позволяет быстро вычислять хеш любой подматрицы и находить одинаковые подматрицы в матрице символов.
Алгоритм ищет максимальный размер квадратной подматрицы, которая встречается в матрице дважды (пересекаться может). Используется бинарный поиск по размеру.
Временная сложность: O(n×k×log n) — построение O(n×k), проверка каждого размера O(n×k).
Пространственная сложность: O(n×k) для хранения хешей и степеней.
Ввод:
n k — размеры матрицы (n строк, k столбцов)Вывод:
4 4
abac
bcab
caba
abac
Вывод:
2
1 1
3 3
Пояснение: подматрица 2×2 "ab" в позиции (1,1) и (3,3) совпадают.
Введите матрицу и найдите одинаковые подматрицы: