Cod sursa(job #1597736)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 12 februarie 2016 11:48:47
Problema Substr Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.31 kb
#include <stdio.h>
#include <algorithm>
#include <string.h>

#define MAX_N 16384
#define MIN(A, B) ((A) < (B) ? (A) : (B))

char S[MAX_N + 1];

// pentru Suffix Array
int order[MAX_N];
int SA[MAX_N];
int classes[MAX_N];
int C[MAX_N];
int FRQ[MAX_N];
int SATMP[MAX_N];

struct Scmp {
  inline
  bool operator () ( const int &A, const int &B ) const {
    return S[A] < S[B];
  }
};

// pentru LCP
int RANK[MAX_N];
int LCP[MAX_N];

int RMQ[15][MAX_N];

int LOG[MAX_N];

int main() {
  FILE *fin, *fout;
  int N, K;

  fin = fopen( "substr.in", "r" );
  fscanf( fin, "%d%d\n", &N, &K );
  fgets( S, MAX_N + 1, fin );
  fclose( fin );

  // Suffix Array

  for ( int i = 0; i < N; i++ ) {
    order[i] = N - i - 1;
  }

  std::sort( order, order + N, Scmp() );

  for ( int i = 0; i < N; i++ ) {
    SA[i] = order[i];
    classes[i] = static_cast <int> (S[i]);
  }

  for ( int length = 1; length < N; length <<= 1 ) {
    memmove( C, classes, 4 * N );

    for ( int i = 0; i < N; i++ ) {
      classes[SA[i]] = i > 0 && C[SA[i-1]] == C[SA[i]] && SA[i-1] + length < N && C[SA[i-1] + (length >> 1)] == C[SA[i] + (length >> 1)] ? classes[SA[i-1]] : i;
    }

    for ( int i = 0; i < N; i++ ) {
      FRQ[i] = i;
    }

    memmove( SATMP, SA, 4 * N );

    for ( int i = 0; i < N; i++ ) {
      int S1 = SATMP[i] - length;

      if ( S1 >= 0 ) {
        SA[ FRQ[classes[S1]]++ ] = S1;
      }
    }
  }

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

  int height = 0;
  for ( int i = 0; i < N; i++ ) {
    int k = RANK[i];
    if ( k > 0 ) {
      int j = SA[k-1];

      while ( S[i + height] == S[j + height] )
        height++;

      LCP[k] = height;

      height -= ( height > 0 );
    }
  }

  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 < N; j++ )
      RMQ[i][j] = MIN( RMQ[i-1][j], RMQ[i-1][j + (1<<(i-1))] );
  }

  int logK = 31 - __builtin_clz( K );
  int ret = 0;

  for ( int i = 0; i < N - K + 1; i++ ) {
    int lcp = ( K == 1 ) ? N - i : MIN( RMQ[logK][i], RMQ[logK][i + K - 1 + (1 << logK)] );

    if ( lcp > ret )
      ret = lcp;
  }

  fout = fopen( "substr.out", "w" );
  fprintf( fout, "%d\n", ret );
  fclose( fout );
  return 0;
}