Cod sursa(job #3143705)

Utilizator NanuGrancea Alexandru Nanu Data 1 august 2023 15:56:51
Problema Substr Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.82 kb
#include <fstream>
#include <algorithm>
#include <string>

using namespace std;

ifstream fin("substr.in");
ofstream fout("substr.out");

#define DIM 16500
#define LOG 17
typedef pair<pair<int, int>, int> PIII;

int n, k;
int P[LOG + 1][DIM + 1], lg[DIM + 5], a[DIM + 5];
PIII v[DIM + 5];
string s;

//cel mai lung prefix comun;
static inline int lcp(int i, int j) {
  if(i == j)
    return n - i;
  
  int ans = 0;
  for(int k = lg[n]; k >= 0; k--)
    if(P[k][i] == P[k][j]) {
      ans += (1 << k);
      i += (1 << k);
      j += (1 << k);
    }

  return ans;
}

//S(k, j) = Secventa de caractere din intervalul [j, j + 2^k - 1];  
//P[k][j] = Pozitia Sufixului S(k, j), in sirul sortat si incepe pe pozitia j; 
static inline void Build_suffix_array(string s) {
  s = '$' + s;                  //santinela;
  for(int i = 1; i <= n; i++)
    P[0][i] = s[i] - '0';

  for(int k = 1; k <= lg[n] + 2; k++) {
    for(int j = 1; j <= n; j++) {
      int x = (1 << (k - 1));           //lungimea intervalului;
      if(j + x <= n)
        v[j] = {{P[k - 1][j], P[k - 1][j + x]}, j};
      else v[j] = {{P[k - 1][j], -1}, j};
    }

    sort(v + 1, v + n + 1);   //sortez sa;

    int nr = 0;
    for(int j = 1; j <= n; j++) {
      if(v[j].first != v[j - 1].first)    //daca sunt mai multe egale au aceeasi pozitie;
      nr++;

      P[k][v[j].second] = nr;
    }
  }
}

int main() {
  fin >> n >> k;
  fin >> s;

  if(k == 1) {
    fout << n;
    return 0;
  }

  lg[1] = 0;
  for(int i = 2; i <= n; i++)
    lg[i] += lg[i / 2] + 1;
  
  Build_suffix_array(s);

  for(int i = 1; i <= n; i++)
    a[P[lg[n] + 2][i]] = i;

  int ans = 0;
  for(int i = 1; i <= n - k + 1; i++) {
    int aux = lcp(a[i], a[i + k - 1]);
    ans = max(ans, aux);
  }

  fout << ans;

  return 0;
}