Cerinta completa

Greg wants to build a string, of length . Starting with an empty string, he can perform operations:

  1. Add a character to the end of for dollars.
  2. Copy any substring of , and then add it to the end of for dollars.

Calculate minimum amount of money Greg needs to build .

Input Format

The first line contains number of testcases .

The subsequent lines each describe a test case over lines:
The first contains space-separated integers, , , and , respectively.
The second contains (the string Greg wishes to build).

Constraints

  • is composed of lowercase letters only.

Output Format

On a single line for each test case, print the minimum cost (as an integer) to build .

Sample Input

2
9 4 5
aabaacaba
9 8 9
bacbacacb

Sample Output

26
42

Explanation

Test Case 0:
“”;
Append ““; “; cost is
Append ““; “; cost is
Append ““; “; cost is
Copy and append ““; “; cost is
Append ““; “; cost is
Copy and append ““; “; cost is

Summing each cost, we get , so our output for Test Case 1 is .

Test Case 1:
“”;
Append ““; “; cost is
Append ““; “; cost is
Append ““; “; cost is
Copy and append ““; “; cost is
Copy and append ““; “; cost is

Summing each cost, we get , so our output for Test Case 2 is .


Limbajul de programare folosit: cpp20

Cod:

#include <bits/stdc++.h>

using namespace std;

string ltrim(const string &);
string rtrim(const string &);
vector<string> split(const string &);

/*
 * Complete the 'buildString' function below.
 *
 * The function is expected to return an INTEGER.
 * The function accepts following parameters:
 *  1. INTEGER a
 *  2. INTEGER b
 *  3. STRING s
 */

struct SparseMin {
    vector<vector<int>> st;
    vector<int> lg;

    SparseMin() = default;

    explicit SparseMin(const vector<int>& v) {
        build(v);
    }

    void build(const vector<int>& v) {
        int n = (int)v.size();
        if (n == 0) {
            st.clear();
            lg = {0};
            return;
        }

        lg.assign(n + 1, 0);
        for (int i = 2; i <= n; ++i) lg[i] = lg[i / 2] + 1;

        int K = lg[n] + 1;
        st.assign(K, vector<int>(n));
        st[0] = v;

        for (int k = 1; k < K; ++k) {
            int len = 1 << k;
            int half = len >> 1;
            for (int i = 0; i + len <= n; ++i) {
                st[k][i] = min(st[k - 1][i], st[k - 1][i + half]);
            }
        }
    }

    int query(int l, int r) const {
        if (l > r) return INT_MAX;
        int len = r - l + 1;
        int k = lg[len];
        return min(st[k][l], st[k][r - (1 << k) + 1]);
    }
};

struct SuffixArrayData {
    string s;
    int n = 0;
    vector<int> sa;
    vector<int> rk;
    vector<int> lcp;
    SparseMin stLcp;
    SparseMin stSa;

    explicit SuffixArrayData(const string& str) {
        s = str;
        n = (int)s.size();
        buildSA();
        buildLCP();
        stLcp.build(lcp);
        stSa.build(sa);
    }

    void buildSA() {
        sa.resize(n);
        rk.resize(n);
        vector<int> tmp(n);

        for (int i = 0; i < n; ++i) {
            sa[i] = i;
            rk[i] = s[i];
        }

        for (int k = 1;; k <<= 1) {
            auto cmp = [&](int i, int j) {
                if (rk[i] != rk[j]) return rk[i] < rk[j];
                int ri = (i + k < n) ? rk[i + k] : -1;
                int rj = (j + k < n) ? rk[j + k] : -1;
                return ri < rj;
            };

            sort(sa.begin(), sa.end(), cmp);

            tmp[sa[0]] = 0;
            for (int i = 1; i < n; ++i) {
                tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
            }

            rk = tmp;
            if (rk[sa[n - 1]] == n - 1) break;
        }

        vector<int> rankByPos(n);
        for (int i = 0; i < n; ++i) rankByPos[sa[i]] = i;
        rk.swap(rankByPos);
    }

    void buildLCP() {
        if (n <= 1) {
            lcp.clear();
            return;
        }

        lcp.assign(n - 1, 0);
        int h = 0;
        for (int i = 0; i < n; ++i) {
            int r = rk[i];
            if (r == n - 1) {
                h = 0;
                continue;
            }
            int j = sa[r + 1];
            while (i + h < n && j + h < n && s[i + h] == s[j + h]) ++h;
            lcp[r] = h;
            if (h > 0) --h;
        }
    }

    // LCP length between suffixes starting at i and j.
    int lcpSuffix(int i, int j) const {
        if (i == j) return n - i;
        int ri = rk[i], rj = rk[j];
        if (ri > rj) swap(ri, rj);
        return stLcp.query(ri, rj - 1);
    }

    bool hasEarlierOccurrence(int pos, int len) const {
        if (len == 0) return true;
        int r = rk[pos];

        int left = r;
        int lo = 0, hi = r;
        while (lo < hi) {
            int mid = (lo + hi) >> 1;
            if (stLcp.query(mid, r - 1) >= len) hi = mid;
            else lo = mid + 1;
        }
        left = lo;

        int right = r;
        lo = r;
        hi = n - 1;
        while (lo < hi) {
            int mid = (lo + hi + 1) >> 1;
            if (stLcp.query(r, mid - 1) >= len) lo = mid;
            else hi = mid - 1;
        }
        right = lo;

        int minStart = stSa.query(left, right);
        return minStart <= pos - len;
    }

    int longestCopyFrom(int pos) const {
        int lo = 0;
        int hi = n - pos;
        while (lo < hi) {
            int mid = (lo + hi + 1) >> 1;
            if (hasEarlierOccurrence(pos, mid)) lo = mid;
            else hi = mid - 1;
        }
        return lo;
    }
};

int buildString(int a, int b, string s) {
    int n = (int)s.size();

    SuffixArrayData sad(s);

    vector<int> maxCopy(n, 0);
    for (int i = 0; i < n; ++i) {
        maxCopy[i] = sad.longestCopyFrom(i);
    }

    const long long INF = (1LL << 60);
    vector<long long> dp(n + 1, INF);
    dp[0] = 0;

    for (int i = 0; i < n; ++i) {
        if (dp[i] == INF) continue;

        dp[i + 1] = min(dp[i + 1], dp[i] + a);

        int len = maxCopy[i];
        if (len > 0) {
            dp[i + len] = min(dp[i + len], dp[i] + b);
        }
    }

    return (int)dp[n];
}

int main()
{
    ofstream fout(getenv("OUTPUT_PATH"));

    string t_temp;
    getline(cin, t_temp);

    int t = stoi(ltrim(rtrim(t_temp)));

    for (int t_itr = 0; t_itr < t; t_itr++) {
        string first_multiple_input_temp;
        getline(cin, first_multiple_input_temp);

        vector<string> first_multiple_input = split(rtrim(first_multiple_input_temp));

        int n = stoi(first_multiple_input[0]);

        int a = stoi(first_multiple_input[1]);

        int b = stoi(first_multiple_input[2]);

        string s;
        getline(cin, s);

        int result = buildString(a, b, s);

        fout << result << endl;
    }

    fout.close();

    return 0;
}

string ltrim(const string &str) {
    string s(str);

    s.erase(
        s.begin(),
        find_if(s.begin(), s.end(), not1(ptr_fun<int, int>(isspace)))
    );

    return s;
}

string rtrim(const string &str) {
    string s(str);

    s.erase(
        find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(),
        s.end()
    );

    return s;
}

vector<string> split(const string &str) {
    vector<string> tokens;

    string::size_type start = 0;
    string::size_type end = 0;

    while ((end = str.find(" ", start)) != string::npos) {
        tokens.push_back(str.substr(start, end - start));

        start = end + 1;
    }

    tokens.push_back(str.substr(start));

    return tokens;
}

Scor obtinut: 1.0

Submission ID: 464636396

Link challenge: https://www.hackerrank.com/challenges/build-a-string/problem

Build a String