Cod sursa(job #2385446)

Utilizator preda.andreiPreda Andrei preda.andrei Data 21 martie 2019 21:50:09
Problema Substr Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.69 kb
#include <algorithm>
#include <fstream>
#include <string>
#include <tuple>
#include <vector>

using namespace std;

using Triplet = tuple<int, int, int>;

vector<vector<int>> GetPrefixes(const string &str)
{
    vector<pair<char, int>> chars(str.size());
    for (size_t i = 0; i < str.size(); i += 1) {
        chars[i] = {str[i], i};
    }
    sort(chars.begin(), chars.end());

    vector<vector<int>> d(str.size());
    auto order = 0;

    for (size_t i = 0; i < str.size(); i += 1) {
        if (i > 0 && chars[i].first != chars[i - 1].first) {
            order += 1;
        }
        d[chars[i].second].push_back(order);
    }

    for (size_t k = 1; (1 << k) < (int)str.size(); k += 1) {
        vector<Triplet> vec(str.size());
        for (size_t i = 0; i < str.size(); i += 1) {
            get<0>(vec[i]) = d[i][k - 1];
            get<1>(vec[i]) = (i + (1 << (k - 1))) < d.size() ? d[i + (1 << (k - 1))][k - 1] : -1;
            get<2>(vec[i]) = i;
        }
        sort(vec.begin(), vec.end());

        auto order = 0;
        for (size_t i = 0; i < str.size(); i += 1) {
            if (i > 0) {
                auto pair1 = make_pair(get<0>(vec[i - 1]), get<1>(vec[i - 1]));
                auto pair2 = make_pair(get<0>(vec[i]), get<1>(vec[i]));
                order += (pair1 != pair2 ? 1 : 0);
            }
            d[get<2>(vec[i])].push_back(order);
        }
    }
    return d;
}

int GetMaxPrefix(const vector<vector<int>> &prefix, int a, int b)
{
    int k = prefix[a].size() - 1;
    int res = 0;

    while (k >= 0) {
        if (prefix[a][k] == prefix[b][k]) {
            res += min<int>((1 << k), prefix.size() - max(a, b));
            a += (1 << k);
            b += (1 << k);

            if (a >= (int)prefix.size() || b >= (int)prefix.size()) {
                break;
            }
        }
        k -= 1;
    }
    return res;
}

int Solve(const string &str, int times)
{
    auto prefix = GetPrefixes(str);

    vector<pair<int, int>> pairs(str.size());
    for (size_t i = 0; i < str.size(); i += 1) {
        pairs[i] = {prefix[i].back(), -(int)i};
    }
    sort(pairs.begin(), pairs.end());

    vector<int> order(str.size());
    for (size_t i = 0; i < str.size(); i += 1) {
        order[i] = -pairs[i].second;
    }

    auto res = 0;
    for (size_t i = 0; i + times - 1 < str.size(); i += 1) {
        auto o1 = order[i];
        auto o2 = order[i + times - 1];
        res = max(res, GetMaxPrefix(prefix, o1, o2));
    }
    return res;
}

int main()
{
    ifstream fin("substr.in");
    ofstream fout("substr.out");

    int len, times;
    fin >> len >> times;
    fin.get();

    string str;
    getline(fin, str);

    auto res = Solve(str, times);
    fout << res << "\n";

    return 0;
}