CF961F k-substrings(哈希 + 二分 + 线段树)
哈希 + 二分 + 线段树
首先需要转变一下角度,容易发现如果按每个
显然可以二分,并且判断字符串相等可以用字符串哈希解决。那么假如半径为
找个数据结构维护。观察到所有等差数列的差值都为
复杂度
#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_back
using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10, p = 20242024, mod = 1234567891;
int n;
std::string s;
i64 hsh[N], pw[N];
bool check(int x, int i, int j) {
int l1 = i - x + 1, r1 = i + x - 1, l2 = j - x + 1, r2 = j + x - 1;
if(l1 < 1 || r2 > n || l2 < 1 || l2 > n) return 0;
i64 ret1 = (hsh[r1] - hsh[l1 - 1] * pw[2 * x - 1] % mod + mod) % mod, ret2 = (hsh[r2] - hsh[l2 - 1] * pw[2 * x - 1] % mod + mod) % mod;
if(ret1 == ret2) return 1;
return 0;
}
struct SEG {
int max, lzy;
} t[N << 2];
void pushup(int u) {
t[u].max = std::max(t[u << 1].max, t[u << 1 | 1].max);
}
void mdf(int u, int x) {
t[u].max = std::max(t[u].max, x);
t[u].lzy = std::max(t[u].lzy, x);
}
void pd(int u) {
if(!t[u].lzy) return;
mdf(u << 1, t[u].lzy), mdf(u << 1 | 1, t[u].lzy);
t[u].lzy = 0;
}
void upd(int u, int l, int r, int L, int R, int x) {
if(L <= l && r <= R) {
mdf(u, x);
return;
}
int mid = (l + r) >> 1; pd(u);
if(L <= mid) upd(u << 1, l, mid, L, R, x);
if(R > mid) upd(u << 1 | 1, mid + 1, r, L, R, x);
pushup(u);
}
int qry(int u, int l, int r, int x) {
if(l == r) return t[u].max;
int mid = (l + r) >> 1; pd(u);
if(x <= mid) return qry(u << 1, l, mid, x);
return qry(u << 1 | 1, mid + 1, r, x);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> s;
s = '#' + s;
for(int i = 1; i <= n; i++) {
hsh[i] = (hsh[i - 1] * p + s[i]) % mod;
}
pw[0] = 1;
for(int i = 1; i <= n; i++) pw[i] = pw[i - 1] * p % mod;
for(int i = 1; i <= (n + 1) / 2; i++) {
int j = n - i + 1, l = 1, r = n, ret = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if(check(mid, i, j)) l = mid + 1, ret = mid;
else r = mid - 1;
}
if(ret) {
l = i - ret + 1, r = i;
if(j + ret - 1 - l + 1 == 2 * ret - 1) continue;
upd(1, 1, n, l, r, 2 * ret - 1 + 2 * l);
}
}
for(int i = 1; i <= (n + 1) / 2; i++) {
int ret = qry(1, 1, n, i) - 2 * i;
std::cout << (ret > 0 ? ret : -1) << " \n"[i == (n + 1) / 2];
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具