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

#include <bits/stdc++.h>
using namespace std;
#define int ll
#define ll long long
#define I32_MAX 2147483647
#define I64_MAX 9223372036854775807LL
#define I64_MAX2 1223372036854775807LL
#define INF I64_MAX2
#define MOD 1000000007
// #define MOD 998244353
#define MEM_SIZE 101010
#define DEBUG_OUT true
#define ALL(x) (x).begin(), (x).end()

template <typename T> void DEBUG(T e) {
  if (DEBUG_OUT == false)
    return;
  std::cout << e << " ";
}
template <typename T> void DEBUG(const std::vector<T> &v) {
  if (DEBUG_OUT == false)
    return;
  for (const auto &e : v) {
    std::cout << e << " ";
  }
  std::cout << std::endl;
}
template <typename T> void DEBUG(const std::vector<std::vector<T>> &vv) {
  if (DEBUG_OUT == false)
    return;
  for (const auto &v : vv) {
    DEBUG(v);
  }
}
template <class T, class... Ts> void DEBUG(T d, Ts... e) {
  if (DEBUG_OUT == false)
    return;
  DEBUG(d);
  DEBUG(e...);
}
template <class T> void corner(bool flg, T hoge) {
  if (flg) {
    cout << hoge << endl;
    abort();
  }
}
template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) {
  return a < b && (a = b, true);
}
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) {
  return a > b && (a = b, true);
}

// BELOW
template <int K, class T> struct Trie {
  struct Node {
    int c;
    std::array<int, K> nxt;
    std::array<int, K> cnt; // 文字cを含むような子孫の数
    int sz;                 // 部分木のサイズ

    explicit Node(int c) : c(c), sz(0) {
      nxt.fill(-1);
      cnt.fill(0);
    }
  };

  std::vector<Node> nodes;
  std::function<int(T)> enc;

  explicit Trie(T base) {
    nodes.emplace_back(-1);
    enc = [=](T c) { return c - base; };
  }

  explicit Trie(const std::function<int(T)> &enc) : enc(enc) {
    nodes.emplace_back(-1);
  }

  template <class Container> void add(const Container &s) {
    int pos = 0;
    for (T c : s) {
      int ci = enc(c);

      int npos = nodes[pos].nxt[ci];
      if (npos == -1) {
        npos = nodes.size();
        nodes[pos].nxt[ci] = npos;
        nodes.emplace_back(ci);
      }
      pos = npos;
    }

    ++nodes[pos].sz;
  }

  template <class Container> int find(const Container &s) const {
    int pos = 0;
    for (char c : s) {
      int ci = enc(c);
      pos = nodes[pos].nxt[ci];
      if (pos == -1)
        return -1;
    }
    return pos;
  }

  // cntを埋める
  void fillcnt() {
    for (int pos = (int)nodes.size() - 1; pos >= 0; --pos) {
      auto &node = nodes[pos];

      for (int c = 0; c < 26; ++c) {
        int npos = node.nxt[c];
        if (npos == -1)
          continue;

        const auto &cnode = nodes[npos];
        node.sz += cnode.sz;
        for (int d = 0; d < 26; ++d) {
          node.cnt[d] += cnode.cnt[d];
        }
      }

      // 全ての子孫はcを含む
      if (node.c != -1)
        node.cnt[node.c] = node.sz;
    }
  }
};

// BELOW
void solve(void) {
  int n;
  cin >> n;
  vector<string> vs(n);
  for (int i = 0; i < n; i++) {
    cin >> vs[i];
    reverse(ALL(vs[i]));
  }
  Trie<26, char> trie('a');
  for (auto &&s : vs) {
    trie.add(s);
  }
  trie.fillcnt();
  int res = 0;
  for (auto &&s : vs) {
    int last = s.back() - 'a';
    s.pop_back();
    int pos = trie.find(s);
    for (int ci = 0; ci < 26; ci++) {
      int npos = trie.nodes[pos].nxt[ci];
      if (npos == -1)
        continue;
      res += trie.nodes[npos].cnt[last];
      if (ci == last)
        res--;
    }
  }
  cout << res << endl;

  return;
}

int32_t main(int32_t argc, const char *argv[]) {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);

  std::cout << std::fixed;
  std::cout << std::setprecision(11);
  solve();

  return 0;
}


Error: -6
terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string: construction from null is not valid


Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define int ll
#define ll long long
#define I32_MAX 2147483647
#define I64_MAX 9223372036854775807LL
#define I64_MAX2 1223372036854775807LL
#define INF I64_MAX2
#define MOD 1000000007
// #define MOD 998244353
#define MEM_SIZE 101010
#define DEBUG_OUT true
#define ALL(x) (x).begin(), (x).end()

template <typename T> void DEBUG(T e) {
  if (DEBUG_OUT == false)
    return;
  std::cout << e << " ";
}
template <typename T> void DEBUG(const std::vector<T> &v) {
  if (DEBUG_OUT == false)
    return;
  for (const auto &e : v) {
    std::cout << e << " ";
  }
  std::cout << std::endl;
}
template <typename T> void DEBUG(const std::vector<std::vector<T>> &vv) {
  if (DEBUG_OUT == false)
    return;
  for (const auto &v : vv) {
    DEBUG(v);
  }
}
template <class T, class... Ts> void DEBUG(T d, Ts... e) {
  if (DEBUG_OUT == false)
    return;
  DEBUG(d);
  DEBUG(e...);
}
template <class T> void corner(bool flg, T hoge) {
  if (flg) {
    cout << hoge << endl;
    abort();
  }
}
template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) {
  return a < b && (a = b, true);
}
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) {
  return a > b && (a = b, true);
}

// BELOW
template <int K, class T> struct Trie {
  struct Node {
    int c;
    std::array<int, K> nxt;
    std::array<int, K> cnt; // 文字cを含むような子孫の数
    int sz;                 // 部分木のサイズ

    explicit Node(int c) : c(c), sz(0) {
      nxt.fill(-1);
      cnt.fill(0);
    }
  };

  std::vector<Node> nodes;
  std::function<int(T)> enc;

  explicit Trie(T base) {
    nodes.emplace_back(-1);
    enc = [=](T c) { return c - base; };
  }

  explicit Trie(const std::function<int(T)> &enc) : enc(enc) {
    nodes.emplace_back(-1);
  }

  template <class Container> void add(const Container &s) {
    int pos = 0;
    for (T c : s) {
      int ci = enc(c);

      int npos = nodes[pos].nxt[ci];
      if (npos == -1) {
        npos = nodes.size();
        nodes[pos].nxt[ci] = npos;
        nodes.emplace_back(ci);
      }
      pos = npos;
    }

    ++nodes[pos].sz;
  }

  template <class Container> int find(const Container &s) const {
    int pos = 0;
    for (char c : s) {
      int ci = enc(c);
      pos = nodes[pos].nxt[ci];
      if (pos == -1)
        return -1;
    }
    return pos;
  }

  // cntを埋める
  void fillcnt() {
    for (int pos = (int)nodes.size() - 1; pos >= 0; --pos) {
      auto &node = nodes[pos];

      for (int c = 0; c < 26; ++c) {
        int npos = node.nxt[c];
        if (npos == -1)
          continue;

        const auto &cnode = nodes[npos];
        node.sz += cnode.sz;
        for (int d = 0; d < 26; ++d) {
          node.cnt[d] += cnode.cnt[d];
        }
      }

      // 全ての子孫はcを含む
      if (node.c != -1)
        node.cnt[node.c] = node.sz;
    }
  }
};

// BELOW
void solve(void) {
  int n;
  cin >> n;
  vector<string> vs(n, 0);
  for (int i = 0; i < n; i++) {
    cin >> vs[i];
    reverse(ALL(vs[i]));
  }
  Trie<26, char> trie('a');
  for (auto &&s : vs) {
    trie.add(s);
  }
  trie.fillcnt();
  int res = 0;
  for (auto &&s : vs) {
    int last = s.back() - 'a';
    s.pop_back();
    int pos = trie.find(s);
    for (int ci = 0; ci < 26; ci++) {
      int npos = trie.nodes[pos].nxt[ci];
      if (npos == -1)
        continue;
      res += trie.nodes[npos].cnt[last];
      if (ci == last)
        res--;
    }
  }
  cout << res << endl;

  return;
}

int32_t main(int32_t argc, const char *argv[]) {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);

  std::cout << std::fixed;
  std::cout << std::setprecision(11);
  solve();

  return 0;
}