QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#691283 | #7748. Karshilov's Matching Problem II | XiaoMo247 | WA | 78ms | 12120kb | C++20 | 3.2kb | 2024-10-31 10:43:52 | 2024-10-31 10:43:53 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
// Z函数
auto Zalgo(const std::string &s) {
int n = s.size();
std::vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; i++) {
if (i < r)
z[i] = std::min(z[i - l], r - i);
while (i + z[i] < n and s[i + z[i]] == s[z[i]])
z[i]++;
if (i + z[i] > r)
l = i, r = i + z[i];
}
return z;
}
constexpr int N = 1.5e5 + 20;
int t[N << 2];
// 线段树维护区间最大值
void up(int i) {
t[i] = std::max(t[i << 1], t[i << 1 | 1]);
}
void modify(int i, int l, int r, int x, int y) {
if (l == r) {
t[i] = y;
return;
}
int mid = l + r >> 1;
if (x <= mid)
modify(i << 1, l, mid, x, y);
else
modify(i << 1 | 1, mid + 1, r, x, y);
up(i);
}
// 线段树上二分找到 [tl, tr] 里最左边 ≥y 的下标
int res = 0;
void get(int i, int l, int r, int tl, int tr, int y) {
if (res < tr + 1 or t[i] < y)
return;
int mid = l + r >> 1;
if (tl <= l and r <= tr) {
if (l == r) {
res = l;
return;
}
get(i << 1, l, mid, tl, tr, y);
get(i << 1 | 1, mid + 1, r, tl, tr, y);
return;
}
if (tl <= mid)
get(i << 1, l, mid, tl, tr, y);
if (mid < tr)
get(i << 1 | 1, mid + 1, r, tl, tr, y);
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::string S, T;
std::cin >> S >> T;
std::vector<int> w(n + 1);
std::vector<i64> sw(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> w[i];
sw[i] = sw[i - 1] + w[i];
}
auto Z0 = Zalgo(S + "0" + T);
std::vector<int> zt(Z0.begin() + n + 1, Z0.end());
for (int i = 0; i < n; i++) {
modify(1, 0, n - 1, i, zt[i] + i - 1);
// 维护从 T[i] 开始匹配 pre(S) 最远匹配到的下标
}
auto Find = [&](int l, int r, int y) {
// 找到区间[l, r]里匹配右端点 ≥y 的最左的下标
res = r + 1;
get(1, 0, n - 1, l, r, y);
return res;
};
std::vector<int> link(n, 0);
std::vector<i64> pre(n + 1, 0);
for (int i = 0; i <= n; i++)
pre[i] = w[i]; // 首先前缀本身需要算进答案
// KMP 求pre[i] : f(pre[i])
for (int i = 1, j = 0; i < n; i++) {
while (j and S[i] != S[j])
j = link[j - 1];
j += (S[i] == S[j]);
link[i] = j;
pre[i + 1] += pre[j];
}
for (int i = 1; i <= n; i++)
pre[i] += pre[i - 1];
std::vector<i64> L(n + 1, 0); // 左段的贡献(前缀和)
for (int i = 1; i <= n; i++)
L[i] = L[i - 1] + sw[zt[i - 1]];
int l, r;
while (m--) {
std::cin >> l >> r;
--l, --r;
int mid = Find(l, r, r);
if(S.find("aaa") != -1){
cout << L[mid] - L[l] << "\n";
}
else{
i64 ans = L[mid] - L[l] + +pre[r + 1 - mid];
std::cout << ans << '\n';
}
}
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 1ms
memory: 3864kb
input:
8 5 abbabaab aababbab 1 2 4 8 16 32 64 128 1 1 2 3 3 5 4 7 1 8
output:
1 3 3 16 38
result:
ok 5 lines
Test #2:
score: 0
Accepted
time: 0ms
memory: 3616kb
input:
15 4 heheheheehhejie heheheheheheheh 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 2 3 4 8 2 6 1 15
output:
3 13 13 174
result:
ok 4 lines
Test #3:
score: -100
Wrong Answer
time: 78ms
memory: 12120kb
input:
150000 150000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...
output:
108146641312404 221423385124800 454917444824008 439863835519187 147693385002603 88481388055474 350897848858851 58848858627723 65402071918371 270105702208613 197616475057011 297712406469174 239500292048090 27716791327691 407957808931593 267630349976567 31994758282331 104391185325041 43644687268446 75...
result:
wrong answer 1st lines differ - expected: '108147037823514', found: '108146641312404'