Cod sursa(job #2765797)

Utilizator DragosC1Dragos DragosC1 Data 29 iulie 2021 22:13:20
Problema Substr Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.15 kb
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

#define mxN 16400

int n, K;
string s, aux;

void read() {
    ifstream f("substr.in");
    f >> n >> K;
    f >> s;
    f.close();
}

int rez = -1;

pair<char, int> a[mxN];
int p[mxN], p_new[mxN];
int c[mxN], c_new[mxN];
int cnt[mxN], poz[mxN];

void count_sort() {
    int i, x;
    for (i = 0; i < n; i++) 
        cnt[i] = 0;
    for (i = 0; i < n; i++)
        cnt[c[i]]++;
    poz[0] = 0;
    for (i = 1; i < n; i++)
        poz[i] = poz[i - 1] + cnt[i - 1];
    for (i = 0; i < n; i++) {
        x = c[p[i]];
        p_new[poz[x]] = p[i];
        poz[x]++;
    }
    for (i = 0; i < n; i++)
        p[i] = p_new[i];
}

bool ok2(int ind) {
    for (int i = p[ind]; i < min(s.size(), aux.size() + p[ind]); i++) 
        if (s[i] < aux[i - p[ind]])
            return -1;
        else if (s[i] > aux[i - p[ind]])
            return 1;
    return 0;
}

bool ok(int x) {
    int st, dr, mij, poz1, poz2, c;
    for (int i = 0; i < s.size() - x; i++) {
        aux = s.substr(i, x);
        poz1 = -1, st = 0, dr = n - 1;
        while (st <= dr) {
            mij = (st + dr) / 2;
            c = ok2(mij);
            if (c == 0 || c == 1) {
                if (c == 0)
                    poz1 = mij;
                dr = mij - 1;
            }
            else st = mij + 1;
        }
        poz2 = -1, st = 0, dr = n - 1;
        while (st <= dr) {
            mij = (st + dr) / 2;
            c = ok2(mij);
            if (c == 0 || c == -1) {
                if (c == 0)
                    poz2 = mij;
                st = mij + 1;
            }
            else dr = mij - 1;
        }
        if (poz1 != -1 && poz2 - poz1 + 1 >= K)
            return 1;
    }
    return 0;
}

void solve() {
    int i;
    // suffix array O(nlogn)
    s += '$';
    n++;
    for (i = 0; i < n; i++)
        a[i] = {s[i], i};
    sort(a, a + n);
    for (i = 0; i < n; i++)
        p[i] = a[i].second;
    c[p[0]] = 0;
    for (i = 1; i < n; i++)
        if (a[i].first == a[i - 1].first)
            c[p[i]] = c[p[i - 1]];
        else c[p[i]] = c[p[i - 1]] + 1;
    
    int k = 0;
    pair<int, int> prev, cur;
    while ((1 << k) < n) {
        for (i = 0; i < n; i++)
            p[i] = (p[i] - (1 << k) + n) % n;
        count_sort();
        c_new[p[0]] = 0;
        for (i = 1; i < n; i++) {
            cur = {c[p[i]], c[p[i] + (1 << k) % n]};
            prev = {c[p[i - 1]], c[p[i - 1] + (1 << k) % n]};
            if (cur == prev)
                c_new[p[i]] = c_new[p[i - 1]];
            else c_new[p[i]] = c_new[p[i - 1]] + 1;
        }
        for (i = 0; i < n; i++)
            c[i] = c_new[i];
        k++;
    }
    int st, dr, mij;
    st = 1, dr = n - 1;
    while (st <= dr) {
        mij = (st + dr) / 2;
        if (ok(mij)) {
            rez = mij;
            st = mij + 1;
        }
        else dr = mij - 1;
    }
}

void output() {
    ofstream g("substr.out");
    g << (rez == -1 ? 0 : rez);
    g.close();
}


int main() {
    read();
    solve();
    output();
    return 0;
}