Cod sursa(job #1058810)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 15 decembrie 2013 21:32:20
Problema Substr Scor 100
Compilator cpp Status done
Runda Teme Pregatire ACM Unibuc 2013 Marime 2.26 kb
#include <iostream>
#include <fstream>
#include <cstring>
#include <algorithm>

using namespace std;

const int Nmax  = 20000;
const int Lgmax = 17;

int N, K, gap;
char sir[Nmax];
int SA[Nmax], tmp[Nmax], poz[Nmax], lcp[Nmax], lg[Nmax];
int rmq[Lgmax][Nmax];

inline int cmp( int i, int j )
{
    if ( poz[i] != poz[j] )
            return poz[i] < poz[j];

    i += gap;
    j += gap;

    if ( i < N && j < N )
            return poz[i] < poz[j];
    else
            return i > j;
}

void SuffixArray()
{
    for ( int i = 0; i < N; ++i )
            SA[i] = i,
            poz[i] = sir[i];

    for ( gap = 1; ; gap *= 2 )
    {
        sort( SA, SA + N, cmp );

        for ( int i = 0; i < N - 1; ++i )
                tmp[i + 1] = tmp[i] + cmp( SA[i], SA[i + 1] );

        for ( int i = 0; i < N; ++i )
                poz[ SA[i] ] = tmp[i];

        if ( tmp[N - 1] == N - 1 )
                break;
    }
}

void LCP()
{
    for ( int i = 0, k = 0; i < N; i++ )
            if ( poz[i] != N - 1 )
            {
                for ( int j = SA[ poz[i] + 1 ]; sir[i + k] == sir[j + k]; )
                        k++;

                lcp[ poz[i] ] = k;

                if ( k > 0 )
                        k--;
            }

    lcp[N - 1] = lcp[N] = N;
}

void RMQ()
{
    for ( int i = 0; i <= N; ++i )
            rmq[0][i] = lcp[i];

    for ( int i = 1; ( 1 << i ) <= N; ++i )
            for ( int j = 0; j + ( 1 << i ) - 1 <= N; ++j )
            {
                int p = 1 << ( i - 1 );

                rmq[i][j] = min( rmq[i - 1][j], rmq[i - 1][j + p] );
            }

    for ( int i = 2; i <= N; ++i )
            lg[i] = lg[i / 2] + 1;
}

void solve()
{
    ofstream g("substr.out");

    int st = -1, dr = K - 2;
    int maxim = 0;

    while ( dr <= N - 1 )
    {
        st++;
        dr++;

        int diff = dr - st;
        int k = lg[diff];
        int p = 1 << k;
        int sh = diff - p;

        int minim = min( rmq[k][st], rmq[k][st + sh] );

        maxim = max( maxim, minim );
    }

    g << maxim << "\n";
}

int main()
{
    ifstream f("substr.in");

    f >> N >> K >> sir;

    SuffixArray();
    LCP();
    RMQ();
    solve();

    return 0;
}