結果

問題 No.2162 Copy and Paste 2
コンテスト
ユーザー vjudge1
提出日時 2026-10-08 20:32:47
言語 C++23
(gcc 15.3.0 + boost 1.92.0 + ACL)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
WA  
実行時間 -
コード長 2,205 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 1,980 ms
コンパイル使用メモリ 190,244 KB
実行使用メモリ 18,544 KB
最終ジャッジ日時 2026-10-08 20:33:17
合計ジャッジ時間 9,375 ms
ジャッジサーバーID
(参考情報)
judge4_1 / judge1_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 23 WA * 3
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <algorithm>
#include <iostream>
#include <numeric>
#include <set>
#include <string>
#include <vector>

using namespace std;
using u64 = unsigned long long;

constexpr int BASE = 2333, N = 2e5;

u64 base[N + 1];

void prepare()
{
    base[0] = 1;
    for (int i = 1; i <= N; ++i)
        base[i] = base[i - 1] * BASE;
}

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

    prepare();

    string S;
    cin >> S;

    int n = S.size();
    vector<u64> hsh(n + 1);

    S = ' ' + S;
    for (int i = 1; i <= n; ++i)
        hsh[i] = hsh[i - 1] + S[i] * base[i];

    auto get_hsh = [&](int l, int r) { return (hsh[r] - hsh[l - 1]) * base[N - r]; };

    vector<int> lcp(n + 1); // lcp[i] := the LCP of S and S[i, n]
    for (int i = 1; i <= n; ++i) {
        int l = 1, r = n - i + 1;
        while (l < r) {
            int mid = (l + r + 1) >> 1;
            if (get_hsh(1, mid) == get_hsh(i, i + mid - 1))
                l = mid;
            else
                r = mid - 1;
        }

        if (get_hsh(1, l) == get_hsh(i, i + l - 1))
            lcp[i] = l;
    }

    vector<int> order(n - 1);
    iota(order.begin(), order.end(), 1);
    ranges::sort(order, { }, [&](int i) { return lcp[i + 1]; });

    set<int> valid;
    for (int i = 1; i < n; ++i)
        valid.insert(valid.end(), i);

    int cur = 0;
    vector<int> g(n + 1);
    for (int j = 1; j <= n; ++j) {
        g[j] = max(g[j], g[j - 1]);

        while (cur < n - 1 && lcp[order[cur] + 1] < j)
            valid.erase(order[cur++]);

        int f = g[j] - 1, i = j;
        while (i <= n) {
            auto itr = valid.lower_bound(i);
            if (itr == valid.end())
                break;
            i = *itr;

            if (i + j > n)
                break;
            f += j - 1;
            g[i + j] = max(g[i + j], f);
            i += j;
        }
    }

    cout << n - g[n] << '\n';
    return 0;
}

/*
f(i, j)         -> f(i + 1, j)
f(i, j) - 1     -> f(i, i)
f(i, j) + j - 1 -> f(i + j, j)  (lcp[i] >= j)

g(i) = max_{j <= i} f(i, j)

for each 1 <= j <= n:
    f = g(j) - 1
    for all lcp[i] >= j:
        f += j - 1
        g(i + j) = max(g(i + j), f)
*/
0