codeforces103389F 地图压缩
行列分开做,每个subtask单独哈希压成一维之后拎出来跑一遍kmp获得循环节
无语,有人不开longlong过不去样例觉得自己哈希写错了狂查哈希
(再次:这不比 J 好写我究竟为什么要吊死在一棵树上
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2010;
const ll p = 1331;
const ll mod = 998244353;
char mp[N][N];
ll COL[N][N], ROW[N][N], ppow[N], nex[N], s[N];
ll solve(ll len) {
// memset(nex, 0, sizeof nex);
for (ll i = 2, j = 0; i <= len; ++i) {
while (j && s[i] != s[j + 1]) j = nex[j];
if (s[i] == s[j + 1]) ++j;
nex[i] = j;
}
return len - nex[len];
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
ll n, q;
cin >> n >> q;
for (ll i = 1; i <= n; ++i) {
for (ll j = 1; j <= n; ++j) {
cin >> mp[i][j];
}
}
ppow[0] = 1;
for (ll i = 1; i <= n; ++i) {
ppow[i] = ppow[i - 1] * p % mod;
}
for (ll i = 1; i <= n; ++i) {
for (ll j = 1; j <= n; ++j) {
ROW[i][j] = (ROW[i][j - 1] * p + (mp[i][j] - 'a')) % mod;
COL[j][i] = (COL[j][i - 1] * p + (mp[i][j] - 'a')) % mod;
}
}
while (q--) {
ll x1, x2, y1, y2;
cin >> x1 >> y1 >> x2 >> y2;
for (ll i = x1; i <= x2; ++i) {
s[i - x1 + 1] = (ROW[i][y2] - ROW[i][y1 - 1] * ppow[y2 - y1 + 1] % mod + mod) % mod;
}
ll len = x2 - x1 + 1;
ll resx = solve(len);
for (ll i = y1; i <= y2; ++i) {
s[i - y1 + 1] = (COL[i][x2] - COL[i][x1 - 1] * ppow[x2 - x1 + 1] % mod + mod) % mod;
}
len = y2 - y1 + 1;
ll resy = solve(len);
cout << resx * resy << endl;
}
return 0;
}