Cod sursa(job #2538038)

Utilizator GirafaCuCarapaceGrecuAlexandru GirafaCuCarapace Data 4 februarie 2020 12:21:05
Problema Substr Scor 40
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.17 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cassert>

using namespace std;

const int LOG = 15, N = 17000;

namespace SuffixArray {
    int calc[LOG][N];
    int sa[N], ord[N], lcp[N];///suficsii sortati, pozitia in vectorul sortat
    int n, logn;
    pair < pair < int, int >, int > aux[N];/// < < prima, a doua >, pozitie >
    string s;

    void Build(string _s) {
        s = _s;
        n = s.size();
        assert(n != 1);
        for (int i = 0; i < n; ++i)
            calc[0][i] = s[i];
        for (int k = 1; (1<<(k - 1)) < n; ++k) {
            logn = k;///imi e prea lene sa fac separat
            for (int i = 0; i < n; ++i)
                aux[i] = {{calc[k - 1][i], (i + (1<<(k - 1)) < n ? calc[k - 1][i + (1<<(k - 1))] : -1)}, -i};
            sort(aux, aux + n);///daca nu intra in timp o sa fac counting sort
            for (int i = 0; i < n; ++i)
                calc[k][-aux[i].second] = i;
        }
        for (int i = 0; i < n; ++i)
            sa[calc[logn][i]] = i, ord[i] = calc[logn][i];
    }

    void Kasai() {
        for (int k = 0, i = 0; i < n; ++i, k?k--:0) {
            if (ord[i] == n - 1) {
                k = 0;
                continue;
            }
            int j = sa[ord[i] + 1];
            while (i + k < n && j + k < n && s[i + k] == s[j + k])
                k++;
            lcp[ord[i]] = k;
        }
    }
}

using namespace SuffixArray;

int dq[N];

int main()
{
    ifstream fin("substr.in");
    ofstream fout("substr.out");
    int n, k;
    string s;
    fin >> n >> k >> s;
    if (n == 1)
        return fout << 1, 0;
    Build(s);
    Kasai();
//    for (int i = 0; i < n; ++i)
//        fout << sa[i] << ' ';
//    fout << '\n';
//    for (int i = 0; i < n; ++i)
//        fout << ord[i] << ' ';
//    fout << '\n';
//    for (int i = 0; i < n; ++i)
//        fout << lcp[i] << ' ';
//    fout << '\n';
//    k--;
//    n--;
//    for (int i = 1; i <= n; ++i)
//        v[i] = lcp[i - 1];
//    ///bagam skyline
//    int top(0);
//    v[0] = v[n + 1] = 0;
//    stk[++top] = 0;
//    for (int i = 1; i <= n; ++i) {
//        while (top && v[stk[top]] > v[i])
//            --top;
//        stanga[i] = stk[top];
//        stk[++top] = i;
//    }
//    top = 0;
//    stk[++top] = n + 1;
//    for (int i = n; i >= 1; --i) {
//        while (top && v[stk[top]] >= v[i])
//            --top;
//        dreapta[i] = stk[top];
//        stk[++top] = i;
//    }
//    int ans(0);
//    for (int i = 1; i <= n; ++i) {
//        if (v[stanga[i]] == v[i])
//            continue;
//        if (dreapta[i] - stanga[i] - 1 >= k)
//            ans += v[i] - max(v[stanga[i]], v[dreapta[i]]);
//    }
//    fout << ans;
    ///am citit gresit enuntul don't mind me
    if (k == 1)
        return fout << n, 0;
    int st(0), dr(-1), ans(-1);
    for (int i = 1; i < n; ++i) {
        while (st <= dr && lcp[dq[dr]] >= lcp[i - 1])
            --dr;
        while (st <= dr && dq[st] <= i - k)
            ++st;
        dq[++dr] = i - 1;
        if (i - k >= -1)
            ans = max(ans, lcp[dq[st]]);
    }
    fout << ans;
    return 0;
}