Cod sursa(job #2390895)

Utilizator preda.andreiPreda Andrei preda.andrei Data 28 martie 2019 14:16:02
Problema Substr Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.95 kb
#include <algorithm>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

struct SortData
{
    pair<int, int> halves;
    int index;

    bool operator<(const SortData &other) const
    {
        return halves < other.halves;
    }

    bool operator!=(const SortData &other) const
    {
        return halves != other.halves;
    }
};

vector<int> Normalise(const string &str)
{
    vector<SortData> sorted(str.size());
    for (size_t i = 0; i < str.size(); i += 1) {
        sorted[i].halves = {str[i], -1};
        sorted[i].index = i;
    }
    sort(sorted.begin(), sorted.end());

    vector<int> normal(str.size());
    normal[sorted[0].index] = 0;

    for (size_t i = 1; i < str.size(); i += 1) {
        normal[sorted[i].index] = normal[sorted[i - 1].index];
        if (sorted[i] != sorted[i - 1]) {
            normal[sorted[i].index] += 1;
        }
    }
    return normal;
}

vector<vector<int>> GetOrder(const string &str)
{
    vector<vector<int>> order;
    order.push_back(Normalise(str));

    for (auto i = 1; (1 << (i - 1)) <= (int)str.size(); i += 1) {
        vector<SortData> sorted(str.size());
        for (size_t j = 0; j < str.size(); j += 1) {
            sorted[j].index = j;
            sorted[j].halves.first = order[i - 1][j];

            if (j + (1 << (i - 1)) < str.size()) {
                sorted[j].halves.second = order[i - 1][j + (1 << (i - 1))];
            } else {
                sorted[j].halves.second = -1;
            }
        }
        sort(sorted.begin(), sorted.end());

        order.push_back(vector<int>(str.size()));
        order[i][sorted[0].index] = 0;

        for (size_t j = 1; j < str.size(); j += 1) {
            order[i][sorted[j].index] = order[i][sorted[j - 1].index];
            if (sorted[j] != sorted[j - 1]) {
                order[i][sorted[j].index] += 1;
            }
        }
    }

    return order;
}

int FindLongestPrefix(const vector<vector<int>> &order, size_t x, size_t y)
{
    auto res = 0;
    for (int i = order.size() - 1; i >= 0; i -= 1) {
        if (x + (1 << i) > order[0].size() || y + (1 << i) > order[0].size()) {
            continue;
        }
        if (order[i][x] == order[i][y]) {
            res += (1 << i);
            x += (1 << i);
            y += (1 << i);
        }
    }
    return res;
}

int FindSubstrLen(const string &str, int times)
{
    auto order = GetOrder(str);
    auto res = 0;

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

    for (size_t i = 0; i + times <= str.size(); i += 1) {
        auto a = sorted[i];
        auto b = sorted[i + times - 1];
        res = max(res, FindLongestPrefix(order, a, b));
    }
    return res;
}

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

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

    string str;
    fin >> str;

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

    return 0;
}