Cod sursa(job #3258839)

Utilizator AlexandruBenescuAlexandru Benescu AlexandruBenescu Data 23 noiembrie 2024 20:34:10
Problema Substr Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.02 kb
#include <bits/stdc++.h>
#define L 16390
#define S 15
#define B 80
#define MOD 1000000123
using namespace std;
ifstream fin("substr.in");
ofstream fout("substr.out");

int n, k;
string s;
int ord[S][L], h[L], p[L], inv[L];

int qexp(int a, int b) {
  int p = 1;
  while (b) {
    if (b % 2 == 1)
      p = 1LL * p * a % MOD;
    a = 1LL * a * a % MOD;
    b /= 2;
  }
  return p;
}

void build() {
  p[0] = 1;
  for (int i = 1; i <= n; i++)
    p[i] = 1LL * p[i - 1] * B % MOD;
  inv[n] = qexp(p[n], MOD - 2);
  for (int i = n - 1; i >= 0; i--)
    inv[i] = 1LL * B * inv[i + 1] % MOD;
}

int getHash(int i, int j) {
  return 1LL * inv[i - 1] * (h[j] - h[i - 1] + MOD) % MOD;
}

int lcp(int x, int y) {
  int le = 1, ri = min(n - x, n - y) + 1, best = 0;
  while (le <= ri) {
    int mid = (le + ri) / 2;
    if (getHash(x, x + mid - 1) == getHash(y, y + mid - 1)) {
      best = mid;
      le = mid + 1;
    }
    else
      ri = mid - 1;
  }
  return best;
}

int main() {
  fin >> n >> k >> s;
  s = "#" + s;

  build();

  for (int i = 1; i <= n; i++) {
    h[i] = (1LL * h[i - 1] + 1LL * (s[i] - '0' + 1) * p[i]) % MOD;
    ord[0][i] = s[i];
  }

  for (int bit = 1; bit < S; bit++) {
    vector <pair <pair <int, int>, int>> v;
    for (int i = 1; i <= n; i++) {
      if (i + (1 << (bit - 1)) > n)
        v.push_back({{ord[bit - 1][i], 0}, i});
      else
        v.push_back({{ord[bit - 1][i], ord[bit - 1][i + (1 << (bit - 1))]}, i});
    }
    sort(v.begin(), v.end());
    int ind = 1;
    ord[bit][v[0].second] = ind;
    for (int i = 1; i < n; i++) {
      if (v[i].first == v[i - 1].first)
        ord[bit][v[i].second] = ind;
      else
        ord[bit][v[i].second] = ++ind;
    }
  }

  vector <pair <int, int>> v;
  for (int i = 1; i <= n; i++)
    v.push_back({ord[S - 1][i], i});
  sort(v.begin(), v.end());

  int ans = 0;
  for (int i = 0; i <= n - k; i++)
    ans = max(ans, lcp(v[i].second, v[i + k - 1].second));

  fout << ans << "\n";
  return 0;
}