Cod sursa(job #2450268)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 22 august 2019 14:45:36
Problema Substr Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.43 kb
#include <fstream>
#include <algorithm>
#include <map>
#include <cstring>

using namespace std;

typedef pair < int, int > PII;

ifstream f("substr.in");
ofstream g("substr.out");

const int NMAX = 17e3 + 5, LOGMAX = 15;

int N, K, Log2[NMAX], ans = 0;

int Ord[LOGMAX + 5][NMAX];
PII Code[NMAX];
pair < PII, int > V[NMAX];

char S[NMAX];

int Start[NMAX];

/// Normalization:
map < char, bool > mp;
int ind, cnt[300];
///

static inline void Suffix_Array ()
{
    for(int i = 1; i <= N; ++i)
        Ord[0][i] = cnt[(int)S[i]];

    for(int i = 1; i <= Log2[N] + 2; ++i)
    {
        for(int j = 1; j <= N; ++j)
            Code[j] = {Ord[i - 1][j], (j + (1 << (i - 1)) <= N) ? Ord[i - 1][j + (1 << (i - 1))] : 0};

        for(int j = 1; j <= N; ++j)
            V[j] = {Code[j], j};

        sort(V + 1, V + N + 1);

        int k = 0;

        for(int j = 1; j <= N; ++j)
        {
            if(V[j].first != V[j - 1].first)
                ++k;

            Ord[i][V[j].second] = k;
        }
    }

    return;
}

static inline int LCP (int Left, int Right)
{
    int r = 0;

    if(Left > Right)
        swap(Left, Right);

    int Dim = min(N - Left + 1, N - Right + 1);

    int p2 = Log2[Dim];

    for(int i = p2; i >= 0 && Left <= N && Right <= N; --i)
    {
        if(Ord[i][Left] == Ord[i][Right])
        {
            r += (1 << i);

            Left += (1 << i);
            Right += (1 << i);
        }
    }

    return r;
}

int main()
{
    f.tie(NULL);

    f >> N >> K;

    if(K == 1)
    {
        g << N << '\n';

        return 0;
    }

    if(K == N)
    {
        bool Ok = true;

        for(int i = 2; i <= N && Ok; ++i)
            if(S[i] != S[i - 1])
                Ok = false;

        if(Ok)
            g << 1;
        else
            g << 0;

        g << '\n';

        return 0;
    }

    ///
    Log2[1] = 0;
    for(int i = 2; i <= N; ++i)
        Log2[i] = 1 + Log2[i / 2];
    ///

    ///
    f >> (S + 1);

    for(int i = 1; i <= N; ++i)
        mp[S[i]] = true;

    for(auto it : mp)
    {
        ++ind;

        cnt[(int)it.first] = ind;
    }
    ///

    Suffix_Array();

    for(int i = 1; i <= N; ++i)
        Start[Ord[Log2[N] + 2][i]] = i;

    for(int i = 1; i <= N - K + 1; ++i)
        ans = max(ans, LCP(Start[i], Start[i + K - 1]));

    g << ans << '\n';

    return 0;
}