QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#691295#7748. Karshilov's Matching Problem IIXiaoMo247WA 67ms12128kbC++203.2kb2024-10-31 10:48:532024-10-31 10:48:53

Judging History

你现在查看的是最新测评结果

  • [2024-10-31 10:48:53]
  • 评测
  • 测评结果:WA
  • 用时:67ms
  • 内存:12128kb
  • [2024-10-31 10:48:53]
  • 提交

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'