[BalkanOI 2007] Cipher
我们需要在字符矩阵中统计所有可能的x行y列的子矩阵的出现次数,并找出出现次数最多的那个。
我们使用哈希来表示每个子矩阵。
计算每个子矩阵的哈希值。
使用双哈希来减少哈希冲突的可能性。
行哈希:预先计算每行的前缀哈希值,以便快速计算任意子串的哈希值。
列哈希:对于每个可能的列起始位置,计算所有行的子串哈希值,然后计算这些哈希值的列方向哈希值,从而得到整个子矩阵的哈希值。
使用哈希值对来统计每个子矩阵的出现次数,最后找出出现次数最多的子矩阵的次数。
码风经过ai调试
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll base1 = 131;
const ll base2 = 13331;
const ll base3 = 13131;
const ll base4 = 13331;
const ll mod1 = 1e9+7;
const ll mod2 = 1e9+9;
int main() {
int n, m;
cin >> n >> m;
char** s = new char*[n+1];
for (int i = 0; i <= n; i++) s[i] = new char[m+1];
for (int i = 1; i <= n; i++) {
string line;
getline(cin, line);
for (int j = 1; j <= m; j++) {
s[i][j] = line[j-1];
}
}
int x, y;
cin >> x >> y;
int max_nm = max(n, m) + 10;
ll* pow1 = new ll[max_nm];
ll* pow2 = new ll[max_nm];
ll* pow3 = new ll[max_nm];
ll* pow4 = new ll[max_nm];
pow1[0] = 1;
pow2[0] = 1;
pow3[0] = 1;
pow4[0] = 1;
for (int i = 1; i < max_nm; i++) {
pow1[i] = (pow1[i-1] * base1) % mod1;
pow2[i] = (pow2[i-1] * base2) % mod2;
pow3[i] = (pow3[i-1] * base3) % mod1;
pow4[i] = (pow4[i-1] * base4) % mod2;
}
ll** h1 = new ll*[n+1];
ll** h2 = new ll*[n+1];
for (int i = 0; i <= n; i++) {
h1[i] = new ll[m+1];
h2[i] = new ll[m+1];
}
for (int i = 1; i <= n; i++) {
h1[i][0] = 0;
h2[i][0] = 0;
for (int j = 1; j <= m; j++) {
h1[i][j] = (h1[i][j-1] * base1 + s[i][j]) % mod1;
h2[i][j] = (h2[i][j-1] * base2 + s[i][j]) % mod2;
}
}
map<pair<ll, ll>, int> count_map;
ll max_count = 0;
pair<ll, ll> max_hash;
for (int j = 1; j <= m - y + 1; j++) {
vector<ll> A1(n+1), A2(n+1);
for (int i = 1; i <= n; i++) {
A1[i] = (h1[i][j+y-1] - h1[i][j-1] * pow1[y] % mod1 + mod1) % mod1;
A2[i] = (h2[i][j+y-1] - h2[i][j-1] * pow2[y] % mod2 + mod2) % mod2;
}
vector<ll> col1(n+1), col2(n+1);
col1[0] = 0;
col2[0] = 0;
for (int i = 1; i <= n; i++) {
col1[i] = (col1[i-1] * base3 + A1[i]) % mod1;
col2[i] = (col2[i-1] * base4 + A2[i]) % mod2;
}
for (int i = 1; i <= n - x + 1; i++) {
ll H1 = (col1[i+x-1] - col1[i-1] * pow3[x] % mod1 + mod1) % mod1;
ll H2 = (col2[i+x-1] - col2[i-1] * pow4[x] % mod2 + mod2) % mod2;
pair<ll, ll> key = {H1, H2};
count_map[key]++;
if (count_map[key] > max_count) {
max_count = count_map[key];
max_hash = key;
}
}
}
vector<pair<int, int>> positions;
vector<string> content;
bool content_recorded = false;
for (int j = 1; j <= m - y + 1; j++) {
vector<ll> A1(n+1), A2(n+1);
for (int i = 1; i <= n; i++) {
A1[i] = (h1[i][j+y-1] - h1[i][j-1] * pow1[y] % mod1 + mod1) % mod1;
A2[i] = (h2[i][j+y-1] - h2[i][j-1] * pow2[y] % mod2 + mod2) % mod2;
}
vector<ll> col1(n+1), col2(n+1);
col1[0] = 0;
col2[0] = 0;
for (int i = 1; i <= n; i++) {
col1[i] = (col1[i-1] * base3 + A1[i]) % mod1;
col2[i] = (col2[i-1] * base4 + A2[i]) % mod2;
}
for (int i = 1; i <= n - x + 1; i++) {
ll H1 = (col1[i+x-1] - col1[i-1] * pow3[x] % mod1 + mod1) % mod1;
ll H2 = (col2[i+x-1] - col2[i-1] * pow4[x] % mod2 + mod2) % mod2;
if (H1 == max_hash.first && H2 == max_hash.second) {
positions.push_back({i, j});
if (!content_recorded) {
for (int r = i; r < i + x; r++) {
string line = "";
for (int c = j; c < j + y; c++) {
line += s[r][c];
}
content.push_back(line);
}
content_recorded = true;
}
}
}
}
cout << x << " " << y << endl;
for (const string& line : content) {
cout << line << endl;
}
cout << positions.size() << endl;
sort(positions.begin(),positions.end());
for (const auto& p : positions) {
cout << p.first << " " << p.second << endl;
}
}

浙公网安备 33010602011771号