Cod sursa(job #1597797)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 12 februarie 2016 12:33:36
Problema Substr Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.27 kb
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <deque>

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

char S[MAX_N + 2];

// 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 DQ[MAX_N];

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

  fin = fopen( "substr.in", "r" );
  fscanf( fin, "%d%d\n", &N, &K );

  if ( K == 1 ) {
    fout = fopen( "substr.out", "w" );
    fprintf( fout, "%d\n", N );
    fclose( fout );
    return 0;
  }

  fgets( S, MAX_N + 2, fin );
  fclose( fin );

// Suffix Array

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

  std::stable_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 );
    }
  }

  int ret = 0;
  int st = 0, fn = 0;
  K--;

  for ( int i = 1; i < N; i++ ) {
    while ( st != fn && LCP[DQ[fn-1]] >= LCP[i] )
      fn--;

    DQ[fn++] = i;

    if ( DQ[st] == i - K )
      st++;

    if ( i >= K && ret < LCP[DQ[st]] )
      ret = LCP[DQ[st]];
  }

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