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

#include <bits/stdc++.h>
using Int = long long; // clang-format off
#define REP_(i, a_, b_, a, b, ...) for (Int i = (a), lim##i = (b); i < lim##i; i++)
#define REP(i, ...) REP_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define ALL(v) std::begin(v), std::end(v)
struct SetupIO { SetupIO() { std::cin.tie(nullptr), std::ios::sync_with_stdio(false), std::cout << std::fixed << std::setprecision(13); } } setup_io;
#ifndef dump
#define dump(...)
#endif // clang-format on

/**
 *    author:  knshnb
 *    created: Wed Aug 26 18:57:13 JST 2020
 **/

template <class T, class S> T make_vec(S x) { return x; }
template <class T, class... Ts> auto make_vec(size_t n, Ts... ts) {
  return std::vector<decltype(make_vec<T>(ts...))>(n, make_vec<T>(ts...));
}

template <char margin = 'A', int char_size = 26> struct Trie {
  struct TrieNode {
    std::array<int, char_size> node;
    TrieNode() { node.fill(-1); };
    typename std::array<int, char_size>::iterator begin() {
      return node.begin();
    }
    typename std::array<int, char_size>::iterator end() { return node.end(); }
    int &operator[](int i) { return node[i]; }
  };
  std::vector<TrieNode> tree;
  std::vector<int> num; // 部分木内の個数
  Trie() : tree(1), num(1) {}
  void insert(const std::string &s) {
    num[0]++;
    int t = 0;
    for (char c : s) {
      int d = c - margin;
      if (tree[t][d] == -1) {
        tree[t][d] = tree.size();
        tree.emplace_back();
        num.push_back(0);
      }
      t = tree[t][d];
      num[t]++;
    }
  }
  void erase(const std::string &s) {
    int par = 0;
    num[par]--;
    for (char c : s) {
      int d = c - margin;
      int nxt = tree[par][d];
      assert(nxt != -1 && "s does not exist");
      if (--num[nxt] == 0)
        tree[par][d] = -1;
      par = nxt;
    }
  }
};

signed main() {
  Int n;
  std::cin >> n;
  std::vector<std::string> ss(n);
  REP(i, n) std::cin >> ss[i], std::reverse(ALL(ss[i]));
  std::sort(ALL(ss),
            [&](std::string a, std::string b) { return a.size() < b.size(); });

  Int ans = 0;
  Trie<> t;
  auto num = make_vec<Int>(1, 26, 0);
  for (const std::string &s : ss) {
    Int idx = 0;
    REP(i, s.size() - 1) {
      REP(c, 26) {
        if (num[idx][c] &&
            std::find(s.begin() + i, s.end(), 'a' + c) != s.end())
          ans += num[idx][c];
      }
      Int c = s[i] - 'a';
      if (t.tree[idx][c] == -1) {
        t.tree[idx][c] = t.tree.size();
        t.tree.emplace_back();
        num.emplace_back(26);
      }
      idx = t.tree[idx][c];
    }
    num[idx][s.back() - 'a']++;
  }
  std::cout << ans << std::endl;
}


Error: -11

Fixed submission:

#include <bits/stdc++.h>
using Int = long long; // clang-format off
#define REP_(i, a_, b_, a, b, ...) for (Int i = (a), lim##i = (b); i < lim##i; i++)
#define REP(i, ...) REP_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define ALL(v) std::begin(v), std::end(v)
struct SetupIO { SetupIO() { std::cin.tie(nullptr), std::ios::sync_with_stdio(false), std::cout << std::fixed << std::setprecision(13); } } setup_io;
#ifndef dump
#define dump(...)
#endif // clang-format on

/**
 *    author:  knshnb
 *    created: Sun Aug  9 21:21:46 JST 2020
 **/

template <class T, class S> T make_vec(S x) { return x; }
template <class T, class... Ts> auto make_vec(size_t n, Ts... ts) {
  return std::vector<decltype(make_vec<T>(ts...))>(n, make_vec<T>(ts...));
}

/// @docs src/String/SuffixArray.md
class SuffixArray {
  std::vector<int> sa_is(const std::vector<int> &str, const int k) {
    const int n = str.size();
    std::vector<bool> is_S(n);
    is_S[n - 1] = true;
    std::vector<bool> is_LMS(n);
    std::vector<int> LMSs;
    for (int i = n - 2; i >= 0; i--) {
      is_S[i] = str[i] < str[i + 1] || (str[i] == str[i + 1] && is_S[i + 1]);
    }
    for (int i = 0; i < n; i++) {
      if (is_S[i] & (i == 0 || !is_S[i - 1])) {
        is_LMS[i] = true;
        LMSs.push_back(i);
      }
    }
    std::vector<int> pseudo_sa = induced_sort(str, LMSs, is_S, k);
    std::vector<int> orderedLMSs(LMSs.size());
    int index = 0;
    for (int x : pseudo_sa) {
      if (is_LMS[x]) {
        orderedLMSs[index++] = x;
      }
    }
    pseudo_sa[orderedLMSs[0]] = 0;
    int rank = 0;
    if (orderedLMSs.size() > 1) {
      pseudo_sa[orderedLMSs[1]] = ++rank;
    }
    for (int i = 1; i < orderedLMSs.size() - 1; i++) {
      bool is_diff = false;
      for (int j = 0; j < n; j++) {
        int p = orderedLMSs[i] + j;
        int q = orderedLMSs[i + 1] + j;
        if (str[p] != str[q] || is_LMS[p] != is_LMS[q]) {
          is_diff = true;
          break;
        }
        if (j > 0 && is_LMS[p]) {
          break;
        }
      }
      pseudo_sa[orderedLMSs[i + 1]] = is_diff ? ++rank : rank;
    }
    std::vector<int> new_str(LMSs.size());
    index = 0;
    for (int i = 0; i < n; i++) {
      if (is_LMS[i]) {
        new_str[index++] = pseudo_sa[i];
      }
    }
    std::vector<int> LMS_sa;
    if (rank + 1 == LMSs.size()) {
      LMS_sa = orderedLMSs;
    } else {
      LMS_sa = sa_is(new_str, rank + 1);
      for (int &x : LMS_sa) {
        x = LMSs[x];
      }
    }
    return induced_sort(str, LMS_sa, is_S, k);
  }

  std::vector<int> induced_sort(const std::vector<int> &str,
                                const std::vector<int> &LMSs,
                                const std::vector<bool> &is_S, const int k) {
    int n = str.size();
    std::vector<int> buckets(n);
    std::vector<int> chars(k + 1);
    for (int c : str) {
      chars[c + 1]++;
    }
    for (int i = 0; i < k; i++) {
      chars[i + 1] += chars[i];
    }
    std::vector<int> count(k);
    for (int i = LMSs.size() - 1; i >= 0; i--) {
      int c = str[LMSs[i]];
      buckets[chars[c + 1] - 1 - count[c]++] = LMSs[i];
    }
    count = std::vector<int>(k);
    for (int i = 0; i < n; i++) {
      if (buckets[i] == 0 || is_S[buckets[i] - 1]) {
        continue;
      }
      int c = str[buckets[i] - 1];
      buckets[chars[c] + count[c]++] = buckets[i] - 1;
    }
    count = std::vector<int>(k);
    for (int i = n - 1; i >= 0; i--) {
      if (buckets[i] == 0 || !is_S[buckets[i] - 1]) {
        continue;
      }
      int c = str[buckets[i] - 1];
      buckets[chars[c + 1] - 1 - count[c]++] = buckets[i] - 1;
    }
    return buckets;
  }

public:
  std::string S;
  int N;
  std::vector<int> sa; // sa[i]: suffixが辞書順i番目となる開始位置のindex
  SuffixArray(std::string str_in) : S(str_in), N(str_in.size()) {
    str_in += "$";
    std::vector<int> str(N + 1);
    for (int i = 0; i < N + 1; i++) {
      str[i] = str_in[i] - '$';
    }
    sa = sa_is(str, 128);
    sa.erase(sa.begin());
  }
  int operator[](int index) { return sa[index]; }

  // sizeがTと等しく初めてT以上になるようなSの部分文字列(sa)
  std::vector<int>::iterator lower_bound(std::string T) {
    int l = -1, r = N;
    while (r - l > 1) {
      int mid = (l + r) / 2;
      if (S.compare(sa[mid], T.size(), T) < 0) {
        l = mid;
      } else {
        r = mid;
      }
    }
    return sa.begin() + r;
  }

  // sizeがTと等しく初めてTより大きくなるようなSの部分文字列(sa)
  std::vector<int>::iterator upper_bound(std::string T) {
    int l = -1, r = N;
    while (r - l > 1) {
      int mid = (l + r) / 2;
      if (S.compare(sa[mid], T.size(), T) <= 0) {
        l = mid;
      } else {
        r = mid;
      }
    }
    return sa.begin() + r;
  }

  // S2が部分文字列として何回出現するか
  int count(std::string S2) { return upper_bound(S2) - lower_bound(S2); }
};

/// @docs src/Helper/BinarySearch.md
template <class F>
long long binary_search(long long ok, long long ng, F check) {
  while (std::abs(ok - ng) > 1) {
    long long mid = (ok + ng) / 2;
    (check(mid) ? ok : ng) = mid;
  }
  return ok;
}

/// @docs src/DataStructure/SegmentTree.md
template <class T, class F> struct SegmentTree {
  const F op;
  const T e;
  SegmentTree() {}
  SegmentTree(F op_, T e_) : op(op_), e(e_) {}
  int n;
  std::vector<T> t;
  void set_by_identity(int n_) {
    n = n_;
    t.clear(), t.resize(2 * n, e);
  }
  void set_by_vector(const std::vector<T> &a) {
    n = a.size();
    t.clear(), t.resize(2 * n, e);
    for (int i = 0; i < n; i++)
      t[i + n] = a[i];
    build();
  }
  void build() {
    for (int i = n - 1; i; --i)
      t[i] = op(t[2 * i], t[2 * i + 1]);
  }
  T &operator[](int i) { return t[i + n]; }
  // [l, r)
  T query(int l, int r) const {
    assert(0 <= l && l <= r && r <= n);
    T resl = e, resr = e;
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        resl = op(resl, t[l++]);
      if (r & 1)
        resr = op(t[--r], resr);
    }
    return op(resl, resr);
  }
  // i番目をxに変更
  void update(int i, const T &x) {
    assert(0 <= i && i < n);
    t[i += n] = x;
    while (i >>= 1)
      t[i] = op(t[2 * i], t[2 * i + 1]);
  }
  // i番目にxを作用 (a[i] = op(a[i], x))
  void operate(int i, const T &x) {
    assert(0 <= i && i < n);
    i += n;
    t[i] = op(t[i], x);
    while (i >>= 1)
      t[i] = op(t[2 * i], t[2 * i + 1]);
  }
  friend std::string to_string(const SegmentTree<T, F> &seg) {
    return to_string(std::vector<T>(seg.t.begin() + seg.n, seg.t.end()));
  }
};
template <class T, class F> auto make_segment_tree(F op, T e) {
  return SegmentTree<T, F>(op, e);
}

signed main() {
  Int n;
  std::cin >> n;
  std::string s;
  std::vector<Int> ids(n);
  std::vector<std::string> orig(n);
  REP(i, n) {
    ids[i] = s.size();
    std::string t;
    std::cin >> t;
    std::reverse(t.begin(), t.end());
    orig[i] = t;
    s += t;
    s.push_back('a' - 1);
  }
  dump(s);
  SuffixArray sa(s);
  dump(sa.sa);
  std::vector<Int> ord;
  REP(i, sa.sa.size()) {
    auto it = std::lower_bound(ALL(ids), sa.sa[i]);
    if (it == ids.end())
      continue;
    if (*it == sa.sa[i])
      ord.push_back(it - ids.begin());
  }
  dump(ord);
  assert(ord.size() == n);
  std::vector<std::string> whole(n);
  REP(i, n) whole[i] = orig[ord[i]];
  dump(whole);
  REP(i, n - 1) assert(whole[i - 1] <= whole[i]);

  auto add = [](Int a, Int b) { return a + b; };
  std::vector<SegmentTree<Int, decltype(add)>> segs(
      26, SegmentTree<Int, decltype(add)>(add, 0));
  REP(i, 26) segs[i].set_by_identity(n);
  auto cnt = make_vec<Int>(n, 26, 0);
  REP(i, n) {
    for (char c : whole[i])
      cnt[i][c - 'a']++;
    REP(c, 26) {
      if (cnt[i][c])
        segs[c].operate(i, 1);
    }
  }
  std::vector<Int> len(n);
  Int ans = 0;
  REP(i, n) {
    // Int beg = binary_search(i, n, [&](Int mid) { return len[mid] >= len[i];
    // }); if (len[i] == 0) beg = i;
    Int beg = i;
    REP(j, beg + 1, n + 1) {
      dump(i, j);
      bool ok = true;
      if (j < n && len[j] >= len[i]) {
        REP(k, len[j], whole[i].size() - 1) {
          if (whole[j].size() <= k || whole[i][k] != whole[j][k]) {
            ok = false;
            break;
          }
          char c = whole[i][k] - 'a';
          if (--cnt[j][c] == 0)
            segs[c].operate(j, -1);
          len[j]++;
          assert(len[j] == k + 1);
        }
      } else {
        ok = false;
      }
      if (!ok) {
        dump(i, j, segs);
        ans += segs[whole[i].back() - 'a'].query(i + 1, j);
        break;
      }
    }
  }
  std::cout << ans << std::endl;
}