Cod sursa(job #2326769)

Utilizator DavidLDavid Lauran DavidL Data 23 ianuarie 2019 22:51:15
Problema Substr Scor 30
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.61 kb
#include <bits/stdc++.h>
using namespace std;
ifstream fi("substr.in");
ofstream fo("substr.out");

const int NMAX = 20005;
const int LOG = 20;

struct boss
{
    int ord[2], poz;
};

bool operator <(const boss &a, const boss &b)
{
    if (a.ord[0] != b.ord[0])
        return a.ord[0] < b.ord[0];
    return a.ord[1] < b.ord[1];
}

struct ultraBoss
{
    int ord[LOG];
};

bool operator <(const ultraBoss &a, const ultraBoss &b)
{
    for (int i = 0; i < LOG; i++)
        if (a.ord[i] != b.ord[i])
            return a.ord[i] < b.ord[i];
    return 1;
}

bool operator ==(const ultraBoss &a, const ultraBoss &b)
{
    for (int i = 0; i < LOG; i++)
        if (a.ord[i] != b.ord[i])
            return 0;
    return 1;
}


int n, K;
char A[NMAX];
int P[LOG][NMAX];
boss L[NMAX];
int pas, cnt;

void getSuffixArray()
{
    for (int i = 1; i <= n; i++)
        P[0][i] = A[i] - '0';

    for (pas = 1, cnt = 1; (pas >> 1) < n; cnt++, pas <<= 1)
    {
        for (int i = 1; i <= n; i++)
        {
            L[i].ord[0] = P[cnt - 1][i];
            L[i].ord[1] = i + pas <= n ? P[cnt - 1][i + pas] : -1;
            L[i].poz = i;
        }
        sort(L + 1, L + n + 1);

        for (int i = 1; i <= n; i++)
        {
            if (i > 1 && L[i].ord[0] == L[i - 1].ord[0] && L[i].ord[1] == L[i - 1].ord[1])
                P[cnt][L[i].poz] = P[cnt][L[i - 1].poz];
            else
                P[cnt][L[i].poz] = i;
        }
    }
    cnt--;
}

ultraBoss V[NMAX];

bool ok(int l)
{
    // bagam secventele in V
    for (int i = 1; i + l - 1 <= n; i++)
    {
        for (int j = 0; j < LOG; j++) // sfanta initializare
            V[i].ord[j] = 0;

        int k = 0;
        int put = 16, curr = i;
        while (curr <= i + l - 1)
        {
            if (curr + (1 << put) <= i + l)
                V[i].ord[k++] = P[put][curr], curr += (1 << put);
            put--;
        }
    }

    int m = n - l + 1;
    sort(V + 1, V + m + 1);

    int curr = 1, maxim = 1;
    for (int i = 2; i <= m; i++)
    {
        if (V[i] == V[i - 1])
            curr++;
        else
            curr = 1;
        maxim = max(maxim, curr);
    }

    return maxim >= K;
}

int main()
{
    fi >> n >> K >> A + 1;

    getSuffixArray();

    int st = 0, dr = n + 1; // st sigur, dr sigur nu

    while (dr - st > 1)
    {
        int mij = (st + dr) / 2;
        //cout <<st << " " << dr << ": " << mij << "(" << ok(mij) <<  "\n";
        if (ok(mij))
            st = mij;
        else
            dr = mij;
    }

    fo << st;

    return 0;
}