Problem p02943 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;

#define INF_LL (int64)1e18
#define INF (int32)1e9
#define REP(i, n) for (int64 i = 0; i < (n); i++)
#define FOR(i, a, b) for (int64 i = (a); i < (b); i++)
#define all(x) x.begin(), x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using uint32 = uint_fast32_t;
using int64 = int_fast64_t;
using uint64 = uint_fast64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

const double eps = 1e-10;

template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

template <typename T> vector<T> make_v(size_t a) { return vector<T>(a); }

template <typename T, typename... Ts> auto make_v(size_t a, Ts... ts) {
  return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template <typename T, typename U, typename... V>
typename enable_if<is_same<T, U>::value != 0>::type fill_v(U &u, const V... v) {
  u = U(v...);
}

template <typename T, typename U, typename... V>
typename enable_if<is_same<T, U>::value == 0>::type fill_v(U &u, const V... v) {
  for (auto &e : u)
    fill_v<T>(e, v...);
}

class SA_IS {
private:
  std::string str;
  std::vector<int> sa;
  bool built = false;

  static inline bool is_lms(const std::vector<int> &is_l, size_t idx) {
    return idx > 0 && is_l[idx - 1] && !is_l[idx];
  }

  void create_bin(const std::vector<int> &v, std::vector<int> &bin) {
    std::fill(bin.begin(), bin.end(), 0);
    for (auto &x : v)
      bin[x + 1]++;
    for (int i = 1; i < bin.size(); i++)
      bin[i] += bin[i - 1];
  }

  void set_lms(const std::vector<int> &v, std::vector<int> &sa,
               std::vector<int> &bin, const std::vector<int> &is_l) {
    for (int i = 0; i < v.size(); i++) {
      if (is_lms(is_l, i)) {
        sa[--bin[v[i] + 1]] = i;
      }
    }
    for (int i = 0; i < v.size(); i++) {
      if (is_lms(is_l, i)) {
        bin[v[i] + 1]++;
      }
    }
  }

  void induced_sort(const std::vector<int> &v, std::vector<int> &sa,
                    size_t kind_num, std::vector<int> &bin,
                    const std::vector<int> &is_l) {
    std::vector<int> cnt(kind_num + 2, 0);
    for (int i = 0; i < v.size(); i++) {
      if (sa[i] <= 0 || !is_l[sa[i] - 1])
        continue;
      int kind = v[sa[i] - 1];
      sa[bin[kind] + cnt[kind]++] = sa[i] - 1;
    }
  }

  void reverse_induced_sort(const std::vector<int> &v, std::vector<int> &sa,
                            std::vector<int> &bin,
                            const std::vector<int> &is_l) {
    for (int i = v.size() - 1; i > 0; i--) {
      if (sa[i] <= 0 || is_l[sa[i] - 1])
        continue;
      int kind = v[sa[i] - 1];
      sa[--bin[kind + 1]] = sa[i] - 1;
    }
  }

public:
  SA_IS() : built(false) {}
  SA_IS(const std::string &str_) : str(str_) { build(); }
  SA_IS(std::string &&str_) : str(str_) { build(); }

  std::vector<int> build(const std::vector<int> &v, int kinds) {
    if (v.size() == 1)
      return std::vector<int>(1, 0);
    std::vector<int> bin(kinds + 2, 0), is_l(v.size(), 0);
    std::vector<int> sa(v.size(), -1);

    for (int i = v.size() - 2; i >= 0; i--) {
      is_l[i] = v[i] == v[i + 1] ? is_l[i + 1] : v[i] > v[i + 1];
    }

    create_bin(v, bin);
    set_lms(v, sa, bin, is_l);
    induced_sort(v, sa, kinds, bin, is_l);
    reverse_induced_sort(v, sa, bin, is_l);

    std::vector<int> order(v.size());
    int cur = 0, prev = -1;
    for (int i = 0; i < v.size(); i++)
      if (is_lms(is_l, i))
        order[i] = cur++;

    std::vector<int> next_v(cur);
    cur = -1;
    for (int i = 0; i < v.size(); i++) {
      if (!is_lms(is_l, sa[i]))
        continue;
      bool diff = false;
      for (int d = 0; d < v.size(); d++) {
        if (prev == -1 || v[sa[i] + d] != v[prev + d] ||
            is_l[sa[i] + d] != is_l[prev + d]) {
          diff = true;
          break;
        }
        if (d > 0 && is_lms(is_l, sa[i] + d))
          break;
      }
      if (diff) {
        cur++;
        prev = sa[i];
      }
      next_v[order[sa[i]]] = cur;
    }

    std::vector<int> re_order(next_v.size());
    std::vector<int> next_sa = build(next_v, cur);
    std::fill(sa.begin(), sa.end(), -1);
    for (int i = 0; i < v.size(); i++)
      if (is_lms(is_l, i))
        re_order[order[i]] = i;
    create_bin(v, bin);
    for (int i = next_sa.size() - 1; i >= 0; i--)
      sa[--bin[v[re_order[next_sa[i]]] + 1]] = re_order[next_sa[i]];
    create_bin(v, bin);
    induced_sort(v, sa, kinds, bin, is_l);
    reverse_induced_sort(v, sa, bin, is_l);

    return sa;
  }

  void build() {
    str += '$';
    std::vector<int> v(str.size());
    for (int i = 0; i < str.size(); i++)
      v[i] = str[i];
    sa = build(v, *std::max_element(v.begin(), v.end()));
    sa = std::vector<int>(sa.begin() + 1, sa.end());
    built = true;
    str = str.substr(0, str.size() - 1);
  }

  const std::vector<int> &get_sa() {
    assert(built);
    return sa;
  }

  bool is_upper(const std::string &t, int s_idx) { // t > sa[si]
    int idx = 0;
    s_idx = sa[s_idx];
    while (s_idx + idx < sa.size() && idx < t.size()) {
      if (t[idx] > str[s_idx + idx])
        return true;
      if (t[idx] < str[s_idx + idx])
        return false;
      idx++;
    }
    return (idx < t.size() && s_idx + idx >= str.size());
  }

  int lower_bound(const std::string &t) {
    int l = -1, r = sa.size(), m;
    while (r - l > 1) {
      m = (l + r) >> 1;
      if (is_upper(t, m))
        l = m;
      else
        r = m;
    }
    return r;
  }

  ::std::pair<int, int> bounds(std::string &t) {
    int l = lower_bound(t);
    t.back()++;
    int r = lower_bound(t);
    t.back()--;
    return ::std::pair<int, int>(l, r);
  }

  const int &operator[](const size_t &k) { return sa[k]; }

  const size_t size() { return str.size() - 1; }
};

int main(void) {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int64 N, K;
  string s;
  cin >> N >> K >> s;
  REP(i, min(N, K - 1)) {
    string t = s;
    reverse(all(t));
    t = s + t;
    reverse(all(t));
    SA_IS sa(t);
    sa.build();
    REP(j, sa.size()) {
      if (sa.size() - sa[j] >= N) {
        s = t.substr(sa[j], N);
        break;
      }
    }
    reverse(all(s));
  }
  string t = s;
  reverse(all(t));
  t = s + t;
  SA_IS sa(t);
  sa.build();
  REP(j, sa.size()) {
    if (sa.size() - sa[j] >= N) {
      s = t.substr(sa[j], N);
      cout << s << endl;
      break;
    }
  }
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;

#define INF_LL (int64)1e18
#define INF (int32)1e9
#define REP(i, n) for (int64 i = 0; i < (n); i++)
#define FOR(i, a, b) for (int64 i = (a); i < (b); i++)
#define all(x) x.begin(), x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using uint32 = uint_fast32_t;
using int64 = int_fast64_t;
using uint64 = uint_fast64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

const double eps = 1e-10;

template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

template <typename T> vector<T> make_v(size_t a) { return vector<T>(a); }

template <typename T, typename... Ts> auto make_v(size_t a, Ts... ts) {
  return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template <typename T, typename U, typename... V>
typename enable_if<is_same<T, U>::value != 0>::type fill_v(U &u, const V... v) {
  u = U(v...);
}

template <typename T, typename U, typename... V>
typename enable_if<is_same<T, U>::value == 0>::type fill_v(U &u, const V... v) {
  for (auto &e : u)
    fill_v<T>(e, v...);
}

class SA_IS {
private:
  std::string str;
  std::vector<int> sa;
  bool built = false;

  static inline bool is_lms(const std::vector<int> &is_l, size_t idx) {
    return idx > 0 && is_l[idx - 1] && !is_l[idx];
  }

  void create_bin(const std::vector<int> &v, std::vector<int> &bin) {
    std::fill(bin.begin(), bin.end(), 0);
    for (auto &x : v)
      bin[x + 1]++;
    for (int i = 1; i < bin.size(); i++)
      bin[i] += bin[i - 1];
  }

  void set_lms(const std::vector<int> &v, std::vector<int> &sa,
               std::vector<int> &bin, const std::vector<int> &is_l) {
    for (int i = 0; i < v.size(); i++) {
      if (is_lms(is_l, i)) {
        sa[--bin[v[i] + 1]] = i;
      }
    }
    for (int i = 0; i < v.size(); i++) {
      if (is_lms(is_l, i)) {
        bin[v[i] + 1]++;
      }
    }
  }

  void induced_sort(const std::vector<int> &v, std::vector<int> &sa,
                    size_t kind_num, std::vector<int> &bin,
                    const std::vector<int> &is_l) {
    std::vector<int> cnt(kind_num + 2, 0);
    for (int i = 0; i < v.size(); i++) {
      if (sa[i] <= 0 || !is_l[sa[i] - 1])
        continue;
      int kind = v[sa[i] - 1];
      sa[bin[kind] + cnt[kind]++] = sa[i] - 1;
    }
  }

  void reverse_induced_sort(const std::vector<int> &v, std::vector<int> &sa,
                            std::vector<int> &bin,
                            const std::vector<int> &is_l) {
    for (int i = v.size() - 1; i > 0; i--) {
      if (sa[i] <= 0 || is_l[sa[i] - 1])
        continue;
      int kind = v[sa[i] - 1];
      sa[--bin[kind + 1]] = sa[i] - 1;
    }
  }

public:
  SA_IS() : built(false) {}
  SA_IS(const std::string &str_) : str(str_) { build(); }
  SA_IS(std::string &&str_) : str(str_) { build(); }

  std::vector<int> build(const std::vector<int> &v, int kinds) {
    if (v.size() == 1)
      return std::vector<int>(1, 0);
    std::vector<int> bin(kinds + 2, 0), is_l(v.size(), 0);
    std::vector<int> sa(v.size(), -1);

    for (int i = v.size() - 2; i >= 0; i--) {
      is_l[i] = v[i] == v[i + 1] ? is_l[i + 1] : v[i] > v[i + 1];
    }

    create_bin(v, bin);
    set_lms(v, sa, bin, is_l);
    induced_sort(v, sa, kinds, bin, is_l);
    reverse_induced_sort(v, sa, bin, is_l);

    std::vector<int> order(v.size());
    int cur = 0, prev = -1;
    for (int i = 0; i < v.size(); i++)
      if (is_lms(is_l, i))
        order[i] = cur++;

    std::vector<int> next_v(cur);
    cur = -1;
    for (int i = 0; i < v.size(); i++) {
      if (!is_lms(is_l, sa[i]))
        continue;
      bool diff = false;
      for (int d = 0; d < v.size(); d++) {
        if (prev == -1 || v[sa[i] + d] != v[prev + d] ||
            is_l[sa[i] + d] != is_l[prev + d]) {
          diff = true;
          break;
        }
        if (d > 0 && is_lms(is_l, sa[i] + d))
          break;
      }
      if (diff) {
        cur++;
        prev = sa[i];
      }
      next_v[order[sa[i]]] = cur;
    }

    std::vector<int> re_order(next_v.size());
    std::vector<int> next_sa = build(next_v, cur);
    std::fill(sa.begin(), sa.end(), -1);
    for (int i = 0; i < v.size(); i++)
      if (is_lms(is_l, i))
        re_order[order[i]] = i;
    create_bin(v, bin);
    for (int i = next_sa.size() - 1; i >= 0; i--)
      sa[--bin[v[re_order[next_sa[i]]] + 1]] = re_order[next_sa[i]];
    create_bin(v, bin);
    induced_sort(v, sa, kinds, bin, is_l);
    reverse_induced_sort(v, sa, bin, is_l);

    return sa;
  }

  void build() {
    str += '$';
    std::vector<int> v(str.size());
    for (int i = 0; i < str.size(); i++)
      v[i] = str[i];
    sa = build(v, *std::max_element(v.begin(), v.end()));
    sa = std::vector<int>(sa.begin() + 1, sa.end());
    built = true;
    str = str.substr(0, str.size() - 1);
  }

  const std::vector<int> &get_sa() {
    assert(built);
    return sa;
  }

  bool is_upper(const std::string &t, int s_idx) { // t > sa[si]
    int idx = 0;
    s_idx = sa[s_idx];
    while (s_idx + idx < sa.size() && idx < t.size()) {
      if (t[idx] > str[s_idx + idx])
        return true;
      if (t[idx] < str[s_idx + idx])
        return false;
      idx++;
    }
    return (idx < t.size() && s_idx + idx >= str.size());
  }

  int lower_bound(const std::string &t) {
    int l = -1, r = sa.size(), m;
    while (r - l > 1) {
      m = (l + r) >> 1;
      if (is_upper(t, m))
        l = m;
      else
        r = m;
    }
    return r;
  }

  ::std::pair<int, int> bounds(std::string &t) {
    int l = lower_bound(t);
    t.back()++;
    int r = lower_bound(t);
    t.back()--;
    return ::std::pair<int, int>(l, r);
  }

  const int &operator[](const size_t &k) { return sa[k]; }

  const size_t size() { return str.size() - 1; }
};

int main(void) {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int64 N, K;
  string s;
  cin >> N >> K >> s;
  REP(i, min((int64)20, min(N, K - 1))) {
    string t = s;
    reverse(all(t));
    t = s + t;
    reverse(all(t));
    SA_IS sa(t);
    sa.build();
    REP(j, sa.size()) {
      if (sa.size() - sa[j] >= N) {
        s = t.substr(sa[j], N);
        break;
      }
    }
    reverse(all(s));
  }
  string t = s;
  reverse(all(t));
  t = s + t;
  SA_IS sa(t);
  sa.build();
  REP(j, sa.size()) {
    if (sa.size() - sa[j] >= N) {
      s = t.substr(sa[j], N);
      cout << s << endl;
      break;
    }
  }
}