Cod sursa(job #2846946)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 9 februarie 2022 21:21:03
Problema Substr Scor 50
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3 kb
// This program was written on 09.02.2022
// for problem substr
// by Mircea Rebengiuc

// ans = max( minimum sliding window de lungime K-1 pe lcp[] )

#include <stdio.h>
#include <ctype.h>

#define MAXN 16'384
#define MAXL 14
#define NIL  -1

char str[MAXN + 1];

// sufix arrays
int suffarr[2][MAXN + 1];
int id[2][MAXN][2];

int frecv[MAXN];
int poz[MAXN + 1];// santinela la sfarsit

// kasai
int invsuff[MAXN];
int lcp[MAXN];

// minimum over a sliding window
int deq[MAXN];// obs: nu e nevoie de deq circular
int p = 0, u = 0;
int pv = 0, uv = 0;// intervalul in lcp[]

void push(){
  while( p != u && deq[u - 1] >= lcp[uv] )
    u--;
  
  deq[u++] = lcp[uv++];
}

void pop(){
  if( lcp[pv] == deq[p] )
    p++;
  
  pv++;
}

int query(){
  return deq[p];
}

FILE *fin, *fout;

int main(){
  fin  = fopen("substr.in",  "r");
  fout = fopen("substr.out", "w");
  
  int n, k, i, j, t, curr_len, pref, maxcommon, cand;
  int prev[2];
    
  fscanf( fin, "%d %d ", &n, &k );
  for( i = 0 ; i < n ; i++ ){
    str[i] = fgetc( fin );
    frecv[(int)str[i]]++;
  }
  str[n] = '\0';

  // suffix arrays
  j = 1;
  for( i = 0 ; i < 128 ; i++ )
    if( frecv[i] )
      frecv[i] = j++;
  
  for( i = 0 ; i < n ; i++ ){
    suffarr[0][i] = i;
    id[0][i][0] = frecv[(int)str[i]];
  }

  pref = 1;
  while( id[0][n - 1][0] < n ){// optimizare
    for( i = 0 ; i < n ; i++ )
      invsuff[suffarr[0][i]] = i;

    for( i = 0 ; i < n ; i++ )
      id[0][i][1] = (suffarr[0][i] + pref) < n ? id[0][invsuff[suffarr[0][i] + pref]][0] : 0;
  
    // metoda noua de radix...
    for( t = 0 ; t < 2 ; t++ ){// suffarr[t], id[t][][] ----radix----> suffarr[t^1], id[t^1][][]
      for( i = 0 ; i < n ; i++ )
        poz[i] = frecv[i] = 0;
      for( i = 0 ; i < n ; i++ )
        poz[id[t][i][t^1] + 1]++;
      for( i = 1 ; i < n ; i++ )
        poz[i] += poz[i - 1];
      
      for( i = 0 ; i < n ; i++ ){
        j = poz[id[t][i][t^1]] + (frecv[id[t][i][t^1]]++);
        suffarr[t^1][j] = suffarr[t][i];
        id[t^1][j][0] = id[t][i][0];
        id[t^1][j][1] = id[t][i][1];
      }
    }

    // refacere coduri
    j = 0;
    prev[0] = prev[1] = -1;
    for( i = 0 ; i < n ; i++ ){
      if( prev[0] != id[0][i][0] || prev[1] != id[0][i][1] )
        j++;
      
      prev[0] = id[0][i][0];
      prev[1] = id[0][i][1];
      id[0][i][0] = j;
    }

    pref <<= 1;
  }
  
  // kasai
  suffarr[0][n] = n;
  for( i = 0 ; i < n ; i++ )
    invsuff[suffarr[0][i]] = i;
  
  curr_len = 0;
  for( i = 0 ; i < n ; i++ ){
    j = suffarr[0][invsuff[i] + 1];
    while( str[i + curr_len] == str[j + curr_len] )
      curr_len++;
    
    lcp[invsuff[i]] = curr_len;
    curr_len = curr_len > 0 ? (curr_len - 1) : 0;
  }
  
  // fereastra glisanta de minim...
  k--;
  n--;

  for( i = 1 ; i < k ; i++ )// inseram primele k-1
    push();
  
  maxcommon = 0;
  for( i = k ; i < n ; i++ ){
    push();
    
    cand = query();
    maxcommon = cand > maxcommon ? cand : maxcommon;
    
    pop();
  }
  
  fprintf( fout, "%d\n", maxcommon );
  
  fclose(fin);
  fclose(fout);
  return 0;
}