Problem p02131 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
#define REP(i, a, n) for (ll i((ll)a); i < ((ll)n); i++)
using namespace std;
typedef long long ll;

const ll MAX_N = 500000;
ll n, k;
ll rnk[MAX_N + 1];
ll tmp[MAX_N + 1];

bool compare_sa(ll i, ll j) {
  if (rnk[i] != rnk[j])
    return rnk[i] < rnk[j];
  ll ri = i + k <= n ? rnk[i + k] : -1;
  ll rj = j + k <= n ? rnk[j + k] : -1;
  return ri < rj;
}

vector<ll> construct_sa(const string &S) {
  n = S.length();
  vector<ll> sa(n + 1);
  REP(i, 0, n + 1) sa[i] = i;
  REP(i, 0, n + 1) rnk[i] = i < n ? S[i] : -1;
  for (k = 1; k <= n; k *= 2) {
    sort(sa.begin(), sa.end(), compare_sa);
    tmp[sa[0]] = 0;
    REP(i, 1, n + 1)
    tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
    REP(i, 0, n + 1) rnk[i] = tmp[i];
  }
  return sa;
}

int main(void) {
  ll N, H;
  string S;
  cin >> N >> H >> S;

  vector<ll> a(N, 0);
  REP(i, 0, N - 1) if (S[i] == '0') a[i + 1] += a[i] + 1;

  vector<ll> imos(N + 2, 0);
  REP(i, 0, N) {
    if (S[i] != '0') {
      imos[1] += a[i] + 1;
      imos[N - i + 1] -= a[i] + 1;
    } else {
      imos[1] += a[i] + 1;
      imos[2] -= a[i] + 1;
    }
  }
  REP(i, 0, N + 1) imos[i + 1] += imos[i];

  ll x = 1, cnt = 1;
  while (1) {
    if (cnt <= H && H < cnt + imos[x])
      break;
    cnt += imos[x];
    x++;
  }

  vector<ll> sa = construct_sa(S);
  REP(i, 1, N + 1) {
    ll j = sa[i];
    if ((x == 1 || S[j] != '0') && j + x <= N) {
      if (cnt <= H && H < cnt + a[j] + 1) {
        cout << S.substr(j, x) << endl;
        break;
      }
      cnt += a[j] + 1;
    }
  }
}


Error: -6
a914268d-d09d-4e96-a9f4-aff889fda670.out: /home/alex/Documents/bug-detection/input/Project_CodeNet/data/p02131/C++/s030356749.cpp:73: int main(): Assertion `false' failed.


Fixed submission:

#include <bits/stdc++.h>
#define REP(i, a, n) for (ll i((ll)a); i < ((ll)n); i++)
using namespace std;
typedef long long ll;

const ll MAX_N = 500000;
ll n, k;
ll rnk[MAX_N + 1];
ll tmp[MAX_N + 1];

bool compare_sa(ll i, ll j) {
  if (rnk[i] != rnk[j])
    return rnk[i] < rnk[j];
  ll ri = i + k <= n ? rnk[i + k] : -1;
  ll rj = j + k <= n ? rnk[j + k] : -1;
  return ri < rj;
}

vector<ll> construct_sa(const string &S) {
  n = S.length();
  vector<ll> sa(n + 1);
  REP(i, 0, n + 1) sa[i] = i;
  REP(i, 0, n + 1) rnk[i] = i < n ? S[i] : -1;
  for (ll k = 1; k <= n; k *= 2) {
    sort(sa.begin(), sa.end(), compare_sa);
    tmp[sa[0]] = 0;
    REP(i, 1, n + 1)
    tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
    REP(i, 0, n + 1) rnk[i] = tmp[i];
  }
  return sa;
}

int main(void) {
  ll N, H;
  string S;
  cin >> N >> H >> S;

  vector<ll> a(N, 0);
  REP(i, 0, N - 1) if (S[i] == '0') a[i + 1] += a[i] + 1;

  vector<ll> imos(N + 2, 0);
  REP(i, 0, N) {
    if (S[i] != '0') {
      imos[1] += a[i] + 1;
      imos[N - i + 1] -= a[i] + 1;
    } else {
      imos[1] += a[i] + 1;
      imos[2] -= a[i] + 1;
    }
  }
  REP(i, 0, N + 1) imos[i + 1] += imos[i];

  ll x = 1, cnt = 1;
  while (1) {
    if (cnt <= H && H < cnt + imos[x])
      break;
    cnt += imos[x];
    x++;
  }

  // cerr << "  all: " << N * (N + 1) / 2 << ", " << accumulate(imos.begin(),
  // imos.end(), 0LL) << endl; cerr << "  x: " << x << ", cnt: " << cnt << endl;

  vector<ll> sa = construct_sa(S);
  REP(i, 1, N + 1) {
    ll j = sa[i];
    if ((x == 1 || S[j] != '0') && j + x <= N) {
      if (cnt <= H && H < cnt + a[j] + 1) {
        cout << S.substr(j, x) << endl;
        break;
      }
      cnt += a[j] + 1;
    }
  }
  assert(false);
}