#include #include #include #include #include #include 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 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 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 order(n - 1); iota(order.begin(), order.end(), 1); ranges::sort(order, { }, [&](int i) { return lcp[i + 1]; }); set valid; for (int i = 1; i < n; ++i) valid.insert(valid.end(), i); int cur = 0; vector 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) */