Codeforces
CF Step
Youtube Linkedin Discord Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Code: A Trivial String Problem

#include <bits/stdc++.h>
using namespace std;

int compute_for_string(string &str) {
    int n = str.size();

    vector<int> dp(n, 1);
    // dp[i] = Maximum number of pieces to build str[0...i]

    for (int i = 1; i < n; i++) {
        // Try all starting positions of the last piece.
        // str[0...L - 1] + str[L...i]
        for (int L = 1; L <= i; L++) {
            if (str.substr(L, i - L + 1) == str.substr(0, i - L + 1)) {
                dp[i] = max(dp[i], dp[L - 1] + 1);
            }
        }
    }

    return dp[n - 1];
}

void solve() {
    int n, q;
    cin >> n >> q;
    string str;
    cin >> str;

    while (q--) {
        int l, r;
        cin >> l >> r;
        l--;
        r--;
        string substr = str.substr(l, r - l + 1);
        long long ans = 0;
        for (int j = l; j <= r; j++) {
            string substr = str.substr(l, j - l + 1);
            ans += compute_for_string(substr);
        }
        cout << ans << "\n";
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}
#include <atcoder/string>
#include <bits/stdc++.h>

using namespace std;
using namespace atcoder;

int compute_for_string(string &str) {
    int n = str.size();

    vector<int> z = z_algorithm(str);

    vector<int> dp(n, 1);
    // dp[i] = Maximum number of pieces to build str[0...i]

    for (int i = 1; i < n; i++) {
        // Try all starting positions of the last piece.
        // str[0...L - 1] + str[L...i]
        for (int L = 1; L <= i; L++) {
            if (z[L] >= i - L + 1) {
                dp[i] = max(dp[i], dp[L - 1] + 1);
            }
        }
    }

    return dp[n - 1];
}

void solve() {
    int n, q;
    cin >> n >> q;
    string str;
    cin >> str;

    while (q--) {
        int l, r;
        cin >> l >> r;
        l--;
        r--;
        string substr = str.substr(l, r - l + 1);
        long long ans = 0;
        for (int j = l; j <= r; j++) {
            string substr = str.substr(l, j - l + 1);
            ans += compute_for_string(substr);
        }
        cout << ans << "\n";
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}
#include <atcoder/string>
#include <bits/stdc++.h>

using namespace std;
using namespace atcoder;

vector<int> compute_for_string(string &str) {
    int n = str.size();

    vector<int> z = z_algorithm(str);

    vector<int> dp(n, 1);
    // dp[i] = Maximum number of pieces to build str[0...i]

    for (int i = 1; i < n; i++) {
        // Try all starting positions of the last piece.
        // str[0...L - 1] + str[L...i]
        for (int L = 1; L <= i; L++) {
            if (z[L] >= i - L + 1) {
                dp[i] = max(dp[i], dp[L - 1] + 1);
            }
        }
    }

    return dp;
}

void solve() {
    int n, q;
    cin >> n >> q;
    string str;
    cin >> str;

    while (q--) {
        int l, r;
        cin >> l >> r;
        l--;
        r--;
        long long ans = 0;

        string substr = str.substr(l, r - l + 1);
        vector<int> dp = compute_for_string(substr);
        for (int i = 0; i < (int)dp.size(); i++) {
            ans += dp[i];
        }

        cout << ans << "\n";
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}
#include <atcoder/string>
#include <bits/stdc++.h>

using namespace std;
using namespace atcoder;

vector<int> compute_for_string(string &str) {
    int n = str.size();

    vector<int> z = z_algorithm(str);

    vector<int> dp(n, 1);
    // dp[i] = Maximum number of pieces to build str[0...i]

    // Distribute contribution via prefixes.
    for (int i = 1; i < n; i++) {
        int len = z[i];
        for (int j = i; j < i + len; j++) {
            dp[j] = max(dp[j], dp[i - 1] + 1);
        }
    }

    return dp;
}

void solve() {
    int n, q;
    cin >> n >> q;
    string str;
    cin >> str;

    while (q--) {
        int l, r;
        cin >> l >> r;
        l--;
        r--;
        long long ans = 0;

        string substr = str.substr(l, r - l + 1);
        vector<int> dp = compute_for_string(substr);
        for (int i = 0; i < (int)dp.size(); i++) {
            ans += dp[i];
        }

        cout << ans << "\n";
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}
#include <atcoder/lazysegtree>
#include <atcoder/string>
#include <bits/stdc++.h>

using namespace std;
using namespace atcoder;

using S = int;
using F = int;

S op(S a, S b) { return max(a, b); }
S e() { return 0; }
S mapping(F f, S x) { return max(f, x); }
F composition(F f, F g) { return max(f, g); }
F id() { return 0; }

vector<int> compute_for_string(string &str) {
    int n = str.length();

    vector<int> z = z_algorithm(str);
    vector<int> dp(n, 1);

    lazy_segtree<S, op, e, F, mapping, composition, id> seg(n);

    // dp[0] = 1 already.
    for (int i = 1; i < n; i++) {
        int len = z[i];

        int L = i;
        // Atcoder's segtree has [close, open) range.
        int R = min(n, i + len);
        seg.apply(L, R, dp[i - 1] + 1);

        // Collect all range updates affecting position i, including self-update
        // from i.
        dp[i] = max(dp[i], seg.get(i));
    }

    return dp;
}

void solve() {
    int n, q;
    cin >> n >> q;
    string str;
    cin >> str;

    while (q--) {
        int l, r;
        cin >> l >> r;
        l--;
        r--;
        long long ans = 0;

        string substr = str.substr(l, r - l + 1);
        vector<int> dp = compute_for_string(substr);
        for (int i = 0; i < (int)dp.size(); i++) {
            ans += dp[i];
        }

        cout << ans << "\n";
    }
}

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

    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}
#include <atcoder/string>
#include <bits/stdc++.h>

using namespace std;
using namespace atcoder;

vector<int> compute_for_string(string &str) {
    int n = str.size();

    vector<int> z = z_algorithm(str);

    vector<int> dp(n, 1);
    // dp[i] = Maximum number of pieces to build str[0...i]

    // will_contribute_till[i] stores all ther intervals with left end at i,
    // along with their contribution.
    vector<vector<pair<int, int>>> will_contribute_till(n);
    priority_queue<pair<int, int>> heap; // (value, R)

    // Distribute contribution via prefixes.
    for (int i = 1; i < n; i++) {
        int len = z[i];
        int L = i;
        int R = i + len - 1;

        will_contribute_till[L].push_back({dp[i - 1] + 1, R});

        // Ordering is important.
        // First, activate everything, then remove expired intervals, then
        // update dp[i].

        // Activate all intervals that start at i.
        for (auto [val, R] : will_contribute_till[i]) {
            heap.push({val, R});
        }

        // Remove expired intervals.
        while (!heap.empty() && heap.top().second < i) {
            heap.pop();
        }

        if (!heap.empty()) {
            dp[i] = max(dp[i], heap.top().first);
        }
    }

    return dp;
}

void solve() {
    int n, q;
    cin >> n >> q;
    string str;
    cin >> str;

    while (q--) {
        int l, r;
        cin >> l >> r;
        l--;
        r--;
        long long ans = 0;

        string substr = str.substr(l, r - l + 1);
        vector<int> dp = compute_for_string(substr);
        for (int i = 0; i < (int)dp.size(); i++) {
            ans += dp[i];
        }

        cout << ans << "\n";
    }
}

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

    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}
#include <bits/stdc++.h>
using namespace std;

using ll = long long;

static vector<int> build_z(const string &t) {
    int n = (int)t.size();
    vector<int> z(n, 0);
    if (n == 0)
        return z;
    z[0] = n;

    int l = 0, r = 0;
    for (int i = 1; i < n; ++i) {
        if (i < r)
            z[i] = min(r - i, z[i - l]);
        while (i + z[i] < n && t[z[i]] == t[i + z[i]])
            ++z[i];
        if (i + z[i] > r) {
            l = i;
            r = i + z[i];
        }
    }
    return z;
}

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

    int T;
    cin >> T;
    while (T--) {
        int n, q;
        cin >> n >> q;

        string s;
        cin >> s;

        vector<pair<int, int>> queries(q);
        unordered_map<int, vector<pair<int, int>>> groups;
        groups.reserve(q * 2);

        for (int i = 0; i < q; ++i) {
            int l, r;
            cin >> l >> r;
            queries[i] = {l, r};
            groups[l].push_back({i, r});
        }

        vector<ll> ans(q);

        for (auto &entry : groups) {
            int l = entry.first;
            auto &vec = entry.second;

            int maxR = 0;
            for (auto &it : vec)
                maxR = max(maxR, it.second);

            int m = maxR - l + 1;
            string t = s.substr(l - 1, m);

            vector<int> z = build_z(t);

            vector<int> F(m + 1, 0);
            vector<ll> pref(m + 1, 0);

            vector<pair<int, int>> st;
            st.reserve(m);

            for (int x = 1; x <= m; ++x) {
                int p = x - 1;
                if (p >= 1) {
                    st.push_back({p, p + z[p]});
                }

                while (!st.empty() && st.back().second < x) {
                    st.pop_back();
                }

                int pre = st.empty() ? 0 : st.back().first;
                F[x] = F[pre] + 1;
                pref[x] = pref[x - 1] + F[x];
            }

            for (auto &[idx, r] : vec) {
                int len = r - l + 1;
                ans[idx] = pref[len];
            }
        }

        for (int i = 0; i < q; ++i) {
            cout << ans[i] << '\n';
        }
    }

    return 0;
}