Submission #1354771

#TimeUsernameProblemLanguageResultExecution timeMemory
1354771bakhtiyarnCopy and Paste 3 (JOI22_copypaste3)C++20
100 / 100
235 ms49696 KiB
// chat gpt's code
#include <bits/stdc++.h>
using namespace std;

using int64 = long long;
static const int64 INF = (1LL << 62);

struct HashPair {
    uint64_t h1, h2;
    bool operator<(const HashPair& other) const {
        if (h1 != other.h1) return h1 < other.h1;
        return h2 < other.h2;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    string S;
    int64 A, B, C;
    cin >> N >> S >> A >> B >> C;
    S = " " + S; // 1-indexed

    // Double rolling hash.
    const uint64_t M1 = 1000000007ULL;
    const uint64_t M2 = 1000000009ULL;
    const uint64_t BASE = 911382323ULL;

    vector<uint64_t> p1(N + 1), p2(N + 1), pw1(N + 1), pw2(N + 1);
    pw1[0] = pw2[0] = 1;
    for (int i = 1; i <= N; ++i) {
        pw1[i] = (pw1[i - 1] * BASE) % M1;
        pw2[i] = (pw2[i - 1] * BASE) % M2;
    }
    for (int i = 1; i <= N; ++i) {
        uint64_t x = (uint64_t)(S[i] - 'a' + 1);
        p1[i] = (p1[i - 1] * BASE + x) % M1;
        p2[i] = (p2[i - 1] * BASE + x) % M2;
    }

    auto get_hash = [&](int l, int r) -> HashPair {
        uint64_t x1 = (p1[r] + M1 - (p1[l - 1] * pw1[r - l + 1]) % M1) % M1;
        uint64_t x2 = (p2[r] + M2 - (p2[l - 1] * pw2[r - l + 1]) % M2) % M2;
        return {x1, x2};
    };

    vector<vector<int64>> dp(N + 2, vector<int64>(N + 2, INF));
    for (int i = 1; i <= N; ++i) dp[i][i] = A;

    for (int len = 1; len <= N; ++len) {
        // next[pos] = earliest non-overlapping next occurrence of S[pos..pos+len-1]
        vector<pair<HashPair, int>> v;
        v.reserve(N - len + 1);
        for (int i = 1; i + len - 1 <= N; ++i) {
            v.push_back({get_hash(i, i + len - 1), i});
        }
        sort(v.begin(), v.end(), [](const auto& a, const auto& b) {
            if (a.first < b.first) return true;
            if (b.first < a.first) return false;
            return a.second < b.second;
        });

        vector<int> nxt(N + 2, -1);
        for (int i = 0; i < (int)v.size();) {
            int j = i;
            while (j < (int)v.size() &&
                   !(v[i].first < v[j].first) &&
                   !(v[j].first < v[i].first)) {
                ++j;
            }

            // positions v[i..j-1] share the same substring
            int ptr = i + 1;
            for (int t = i; t < j; ++t) {
                int pos = v[t].second;
                if (ptr < t + 1) ptr = t + 1;
                while (ptr < j && v[ptr].second < pos + len) ++ptr;
                if (ptr < j) nxt[pos] = v[ptr].second;
            }

            i = j;
        }

        for (int l = 1; l + len - 1 <= N; ++l) {
            int r = l + len - 1;
            int64 cur = dp[l][r];
            if (cur >= INF) continue;

            // Type one character to either side.
            if (r + 1 <= N) dp[l][r + 1] = min(dp[l][r + 1], cur + A);
            if (l - 1 >= 1) dp[l - 1][r] = min(dp[l - 1][r], cur + A);

            // Copy-paste chain for this exact substring length.
            if (nxt[l] == -1) continue;

            int64 cost = cur + B + C; // cut, then first paste
            int curEnd = r;
            int p = nxt[l];

            while (p != -1) {
                // Type the gap between consecutive occurrences, then paste once more.
                cost += (int64)(p - curEnd - 1) * A + C;
                curEnd = p + len - 1;
                if (curEnd > N) break;
                dp[l][curEnd] = min(dp[l][curEnd], cost);
                p = nxt[p];
            }
        }
    }

    cout << dp[1][N] << '\n';
    return 0;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...