QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#691295 | #7748. Karshilov's Matching Problem II | XiaoMo247 | WA | 67ms | 12128kb | C++20 | 3.2kb | 2024-10-31 10:48:53 | 2024-10-31 10:48: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 << mid << "\n";
}
else{
i64 ans = L[mid] - L[l] + +pre[r + 1 - mid];
std::cout << ans << '\n';
}
}
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 0ms
memory: 3556kb
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: 3552kb
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: 67ms
memory: 12128kb
input:
150000 150000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...
output:
41993 141886 140609 149447 52882 138592 100008 144297 73492 126191 138499 136041 120119 98574 114892 114348 46077 44097 59817 77805 140177 18712 142074 46716 14075 123806 102628 79355 114556 144922 79743 130030 38058 83326 48183 35455 52790 143795 60539 74252 77805 141417 21717 145425 48430 116828 1...
result:
wrong answer 1st lines differ - expected: '108147037823514', found: '41993'