Problem p02589 (C++) — buggy submission, verdict: Time Limit Exceeded

#define _CRT_SECURE_NO_WARNINGS
// #define POJ
#ifdef POJ
#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <utility>
#include <vector>
#else
#include <bits/stdc++.h>
#include <random>
#include <unordered_set>
#endif
using namespace std;
#define rep(i, a, n) for (int i = a; i < n; i++)
#define per(i, a, n) for (int i = n - 1; i >= a; i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define sz(x) ((int)(x).size())
typedef vector<int> vi;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef double db;
#ifndef POJ
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x; }
#endif
const ll mod = 1000000007;
template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (auto &v : vec)
    is >> v;
  return is;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (auto v : vec)
    os << v << ",";
  os << "]";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const deque<T> &vec) {
  os << "deq[";
  for (auto v : vec)
    os << v << ",";
  os << "]";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &vec) {
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &vec) {
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
#ifndef POJ
template <typename T>
ostream &operator<<(ostream &os, const unordered_set<T> &vec) {
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) {
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename TK, typename TV>
ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp) {
  os << "{";
  for (auto v : mp)
    os << v.first << "=>" << v.second << ",";
  os << "}";
  return os;
}
template <typename T> void resize_array(vector<T> &vec, int len) {
  vec.resize(len);
}
template <typename T, typename... Args>
void resize_array(vector<T> &vec, int len, Args... args) {
  vec.resize(len);
  for (auto &v : vec)
    resize_array(v, args...);
}
#endif
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &pa) {
  os << "(" << pa.first << "," << pa.second << ")";
  return os;
}
template <typename TK, typename TV>
ostream &operator<<(ostream &os, const map<TK, TV> &mp) {
  os << "{";
  for (auto v : mp)
    os << v.first << "=>" << v.second << ",";
  os << "}";
  return os;
}
template <typename T> bool mmax(T &m, const T q) {
  if (m < q) {
    m = q;
    return true;
  } else
    return false;
}
template <typename T> bool mmin(T &m, const T q) {
  if (q < m) {
    m = q;
    return true;
  } else
    return false;
}
template <typename T1, typename T2>
pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) {
  return make_pair(l.first + r.first, l.second + r.second);
}
template <typename T1, typename T2>
pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) {
  return make_pair(l.first - r.first, l.second - r.second);
}
#define dbg(x)                                                                 \\
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ") " << __FILE__ << endl;
ll powmod(ll a, ll b) {
  ll res = 1;
  a %= mod;
  assert(b >= 0);
  for (; b; b >>= 1) {
    if (b & 1)
      res = res * a % mod;
    a = a * a % mod;
  }
  return res;
}
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }

#ifndef POJ
static uint MD = mod;
struct ModInt {
  using M = ModInt;
  uint v;
  ModInt(ll _v = 0) { set_v(uint(_v % MD + MD)); }
  M &set_v(uint _v) {
    v = (_v < MD) ? _v : _v - MD;
    return *this;
  }
  explicit operator bool() const { return v != 0; }
  M operator-() const { return M() - *this; }
  M operator+(const M &r) const { return M().set_v(v + r.v); }
  M operator-(const M &r) const { return M().set_v(v + MD - r.v); }
  M operator*(const M &r) const { return M().set_v(uint(ull(v) * r.v % MD)); }
  M operator/(const M &r) const { return *this * r.inv(); }
  M &operator+=(const M &r) { return *this = *this + r; }
  M &operator-=(const M &r) { return *this = *this - r; }
  M &operator*=(const M &r) { return *this = *this * r; }
  M &operator/=(const M &r) { return *this = *this / r; }
  bool operator==(const M &r) const { return v == r.v; }
  M pow(ll n) const {
    M x = *this, r = 1;
    while (n) {
      if (n & 1)
        r *= x;
      x *= x;
      n >>= 1;
    }
    return r;
  }
  M inv() const { return pow(MD - 2); }
  friend ostream &operator<<(ostream &os, const M &r) { return os << r.v; }
};
using Mint = ModInt;
#endif

class Trie {
  struct Node {
    Node() {
      // memset(next,0,sizeof(next));
      memset(rightest, 0, sizeof(rightest));
      deep = 0;
    }
    int deep;
    int rightest[26]; // a-z
    // Node* next[26];
    unordered_map<char, Node *> next;
  };

public:
  ~Trie() {
    for (auto it = root.next.begin(); it != root.next.end(); it++) {
      deleteNode(it->second);
    }
    root.next.clear();
  }
  void deleteNode(Node *node) {
    if (node == nullptr)
      return;
    for (auto it = node->next.begin(); it != node->next.end(); it++) {
      deleteNode(it->second);
    }
    delete node;
  }
  void addToTrie(string &s, int *rightest) {
    rep(i, 0, 26) {
      if (rightest[i] >= root.deep)
        root.rightest[i]++;
    }
    if (root.next.count(s[0]) == 0) {
      root.next[s[0]] = new Node();
    }
    Node *cur = root.next[s[0]];
    cur->deep = 0;
    rep(i, 0, 26) {
      if (rightest[i] > cur->deep)
        cur->rightest[i]++;
    }
    rep(i, 1, s.length()) {
      if (cur->next.count(s[i]) == 0) {
        cur->next[s[i]] = new Node();
      }
      Node *next = (cur->next[s[i]]);
      next->deep = cur->deep + 1;
      rep(j, 0, 26) {
        if (rightest[j] > next->deep)
          next->rightest[j]++;
      }
      cur = next;
    }
  }
  ll countT(string &s) {
    Node *cur = &root;
    rep(i, 0, s.length() - 1) {
      Node *next = cur->next[s[i]];
      cur = next;
    }
    return cur->rightest[s[s.length() - 1] - 'a'] - 1;
  }
  Node root;
};

class Solution {
public:
  void Solve() {
    int n;
    while (cin >> n) {
      Trie trie;
      vector<string> vs(n);
      rep(i, 0, n) {
        cin >> vs[i];
        int rightest[26];
        memset(rightest, -1, sizeof(rightest));
        reverse(vs[i].begin(), vs[i].end());
        rep(j, 0, vs[i].length()) { rightest[vs[i][j] - 'a'] = j; }

        trie.addToTrie(vs[i], rightest);
      }
      ll ans = 0;
      rep(i, 0, n) { ans += trie.countT(vs[i]); }
      cout << ans << endl;
    }
  }

private:
};
// head
//  cin >> t;
//  for (int cas = 1; cas <= t; ++cas)
//  {
//  	cout << "Case #" << cas << ": ";
//  }
int main() {
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  ios::sync_with_stdio(false);
  cin.tie(0);

  Solution().Solve();

  return 0;
}


Error: TLE

Fixed submission:

#define _CRT_SECURE_NO_WARNINGS
// #define POJ
#ifdef POJ
#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <utility>
#include <vector>
#else
#include <bits/stdc++.h>
#include <random>
#include <unordered_set>
#endif
using namespace std;
#define rep(i, a, n) for (int i = a; i < n; i++)
#define per(i, a, n) for (int i = n - 1; i >= a; i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define sz(x) ((int)(x).size())
typedef vector<int> vi;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef double db;
#ifndef POJ
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x; }
#endif
const ll mod = 1000000007;
template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (auto &v : vec)
    is >> v;
  return is;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (auto v : vec)
    os << v << ",";
  os << "]";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const deque<T> &vec) {
  os << "deq[";
  for (auto v : vec)
    os << v << ",";
  os << "]";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &vec) {
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &vec) {
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
#ifndef POJ
template <typename T>
ostream &operator<<(ostream &os, const unordered_set<T> &vec) {
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) {
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename TK, typename TV>
ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp) {
  os << "{";
  for (auto v : mp)
    os << v.first << "=>" << v.second << ",";
  os << "}";
  return os;
}
template <typename T> void resize_array(vector<T> &vec, int len) {
  vec.resize(len);
}
template <typename T, typename... Args>
void resize_array(vector<T> &vec, int len, Args... args) {
  vec.resize(len);
  for (auto &v : vec)
    resize_array(v, args...);
}
#endif
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &pa) {
  os << "(" << pa.first << "," << pa.second << ")";
  return os;
}
template <typename TK, typename TV>
ostream &operator<<(ostream &os, const map<TK, TV> &mp) {
  os << "{";
  for (auto v : mp)
    os << v.first << "=>" << v.second << ",";
  os << "}";
  return os;
}
template <typename T> bool mmax(T &m, const T q) {
  if (m < q) {
    m = q;
    return true;
  } else
    return false;
}
template <typename T> bool mmin(T &m, const T q) {
  if (q < m) {
    m = q;
    return true;
  } else
    return false;
}
template <typename T1, typename T2>
pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) {
  return make_pair(l.first + r.first, l.second + r.second);
}
template <typename T1, typename T2>
pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) {
  return make_pair(l.first - r.first, l.second - r.second);
}
#define dbg(x)                                                                 \\
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ") " << __FILE__ << endl;
ll powmod(ll a, ll b) {
  ll res = 1;
  a %= mod;
  assert(b >= 0);
  for (; b; b >>= 1) {
    if (b & 1)
      res = res * a % mod;
    a = a * a % mod;
  }
  return res;
}
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }

#ifndef POJ
static uint MD = mod;
struct ModInt {
  using M = ModInt;
  uint v;
  ModInt(ll _v = 0) { set_v(uint(_v % MD + MD)); }
  M &set_v(uint _v) {
    v = (_v < MD) ? _v : _v - MD;
    return *this;
  }
  explicit operator bool() const { return v != 0; }
  M operator-() const { return M() - *this; }
  M operator+(const M &r) const { return M().set_v(v + r.v); }
  M operator-(const M &r) const { return M().set_v(v + MD - r.v); }
  M operator*(const M &r) const { return M().set_v(uint(ull(v) * r.v % MD)); }
  M operator/(const M &r) const { return *this * r.inv(); }
  M &operator+=(const M &r) { return *this = *this + r; }
  M &operator-=(const M &r) { return *this = *this - r; }
  M &operator*=(const M &r) { return *this = *this * r; }
  M &operator/=(const M &r) { return *this = *this / r; }
  bool operator==(const M &r) const { return v == r.v; }
  M pow(ll n) const {
    M x = *this, r = 1;
    while (n) {
      if (n & 1)
        r *= x;
      x *= x;
      n >>= 1;
    }
    return r;
  }
  M inv() const { return pow(MD - 2); }
  friend ostream &operator<<(ostream &os, const M &r) { return os << r.v; }
};
using Mint = ModInt;
#endif

class Trie {
  struct Node {
    Node() {
      // memset(next,0,sizeof(next));
      // memset(rightest,0,sizeof(rightest));
      deep = 0;
      rep(i, 0, 26) { rightest[(char)('a' + i)] = 0; }
    }
    int deep;
    // int rightest[26];//a-z
    // Node* next[26];
    unordered_map<char, int> rightest;
    unordered_map<char, Node *> next;
  };

public:
  ~Trie() {
    for (auto it = root.next.begin(); it != root.next.end(); it++) {
      deleteNode(it->second);
    }
    root.next.clear();
  }
  void deleteNode(Node *node) {
    if (node == nullptr)
      return;
    for (auto it = node->next.begin(); it != node->next.end(); it++) {
      deleteNode(it->second);
    }
    delete node;
  }
  void addToTrie(string &s, int *rightest) {
    rep(i, 0, 26) {
      if (rightest[i] >= root.deep)
        root.rightest[(char)('a' + i)]++;
    }
    if (root.next.count(s[0]) == 0) {
      root.next[s[0]] = new Node();
    }
    Node *cur = root.next[s[0]];
    cur->deep = 0;
    rep(i, 0, 26) {
      if (rightest[i] > cur->deep)
        cur->rightest[(char)('a' + i)]++;
    }
    rep(i, 1, s.length()) {
      if (cur->next.count(s[i]) == 0) {
        cur->next[s[i]] = new Node();
      }
      Node *next = (cur->next[s[i]]);
      next->deep = cur->deep + 1;
      rep(j, 0, 26) {
        if (rightest[j] > next->deep)
          next->rightest[(char)('a' + j)]++;
      }
      cur = next;
    }
  }
  ll countT(string &s) {
    Node *cur = &root;
    rep(i, 0, s.length() - 1) {
      Node *next = cur->next[s[i]];
      cur = next;
    }
    return cur->rightest[s[s.length() - 1]] - 1;
  }
  Node root;
};

class Solution {
public:
  void Solve() {
    int n;
    while (cin >> n) {
      Trie trie;
      vector<string> vs(n);
      rep(i, 0, n) {
        cin >> vs[i];
        int rightest[26];
        memset(rightest, -1, sizeof(rightest));
        reverse(vs[i].begin(), vs[i].end());
        rep(j, 0, vs[i].length()) { rightest[vs[i][j] - 'a'] = j; }

        trie.addToTrie(vs[i], rightest);
      }
      ll ans = 0;
      rep(i, 0, n) { ans += trie.countT(vs[i]); }
      cout << ans << endl;
    }
  }

private:
};
// head
//  cin >> t;
//  for (int cas = 1; cas <= t; ++cas)
//  {
//  	cout << "Case #" << cas << ": ";
//  }
int main() {
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  ios::sync_with_stdio(false);
  cin.tie(0);

  Solution().Solve();

  return 0;
}