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

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(v) (v).begin(), (v).end()
using ll = long long;
constexpr int INF = 1e9;
constexpr long long LINF = 1e18;
constexpr long long MOD = 1e9 + 7;

template <typename T> struct RollingHash {
  using ll = long long;
  ll B_1, B_2, MOD_1, MOD_2;
  vector<ll> hash_1, hash_2, pow_1, pow_2;

  RollingHash(vector<T> v, ll B_1 = 1007, ll B_2 = 1009, ll MOD_1 = 1000000007,
              ll MOD_2 = 1000000009)
      : B_1(B_1), B_2(B_2), MOD_1(MOD_1), MOD_2(MOD_2) {
    init(v);
  }

  RollingHash(string &s, ll B_1 = 1007, ll B_2 = 1009, ll MOD_1 = 1000000007,
              ll MOD_2 = 1000000009)
      : B_1(B_1), B_2(B_2), MOD_1(MOD_1), MOD_2(MOD_2) {
    vector<T> v;
    for (char c : s)
      v.emplace_back(c);
    init(v);
  }

  void init(vector<T> v) {
    int n = v.size();
    hash_1.assign(n + 1, 0);
    hash_2.assign(n + 1, 0);
    pow_1.assign(n + 1, 1);
    pow_2.assign(n + 1, 1);
    for (int i = 0; i < n; i++) {
      hash_1[i + 1] = (hash_1[i] * B_1 + v[i]) % MOD_1;
      hash_2[i + 1] = (hash_2[i] * B_2 + v[i]) % MOD_2;
      pow_1[i + 1] = pow_1[i] * B_1 % MOD_1;
      pow_2[i + 1] = pow_2[i] * B_2 % MOD_2;
    }
  }

  pair<int, int> get(int l, int r) {
    int res_1 =
        ((hash_1[r] - hash_1[l] * pow_1[r - l]) % MOD_1 + MOD_1) % MOD_1;
    int res_2 =
        ((hash_2[r] - hash_2[l] * pow_2[r - l]) % MOD_2 + MOD_2) % MOD_2;
    return pair<ll, ll>(res_1, res_2);
  }
};
signed main() {
  int n;
  cin >> n;
  vector<RollingHash<char>> v;
  string s[n];
  rep(i, n) {
    cin >> s[i];
    RollingHash<char> rh(s[i]);
    v.emplace_back(rh);
  }
  set<pair<int, int>> cnt[26];
  rep(i, n) { cnt[s[i][0] - 'a'].emplace(v[i].get(1, (int)s[i].size())); }
  ll ans = 0;
  rep(i, n) {
    set<int> S;
    S.emplace(s[i][0] - 'a');
    int m = s[i].size();
    for (int j = 1; j <= m; j++) {
      for (int s : S) {
        if (cnt[s].count(v[i].get(j, m)))
          ans++;
      }
      if (j == m)
        continue;
      S.emplace(s[i][j] - 'a');
    }
  }
  cout << ans - n << endl;
  return 0;
}

Error: TLE

Fixed submission:

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(v) (v).begin(), (v).end()
using ll = long long;
constexpr int INF = 1e9;
constexpr long long LINF = 1e18;
constexpr long long MOD = 1e9 + 7;

template <typename T> struct RollingHash {
  using ll = long long;
  ll B_1, B_2, MOD_1, MOD_2;
  vector<ll> hash_1, hash_2, pow_1, pow_2;

  RollingHash(vector<T> v, ll B_1 = 1007, ll B_2 = 1009, ll MOD_1 = 1000000007,
              ll MOD_2 = 1000000009)
      : B_1(B_1), B_2(B_2), MOD_1(MOD_1), MOD_2(MOD_2) {
    init(v);
  }

  RollingHash(string &s, ll B_1 = 1007, ll B_2 = 1009, ll MOD_1 = 1000000007,
              ll MOD_2 = 1000000009)
      : B_1(B_1), B_2(B_2), MOD_1(MOD_1), MOD_2(MOD_2) {
    vector<T> v;
    for (char c : s)
      v.emplace_back(c);
    init(v);
  }

  void init(vector<T> v) {
    int n = v.size();
    hash_1.assign(n + 1, 0);
    hash_2.assign(n + 1, 0);
    pow_1.assign(n + 1, 1);
    pow_2.assign(n + 1, 1);
    for (int i = 0; i < n; i++) {
      hash_1[i + 1] = (hash_1[i] * B_1 + v[i]) % MOD_1;
      hash_2[i + 1] = (hash_2[i] * B_2 + v[i]) % MOD_2;
      pow_1[i + 1] = pow_1[i] * B_1 % MOD_1;
      pow_2[i + 1] = pow_2[i] * B_2 % MOD_2;
    }
  }

  pair<int, int> get(int l, int r) {
    int res_1 =
        ((hash_1[r] - hash_1[l] * pow_1[r - l]) % MOD_1 + MOD_1) % MOD_1;
    int res_2 =
        ((hash_2[r] - hash_2[l] * pow_2[r - l]) % MOD_2 + MOD_2) % MOD_2;
    return pair<ll, ll>(res_1, res_2);
  }
};
signed main() {
  int n;
  cin >> n;
  vector<RollingHash<char>> v;
  string s[n];
  rep(i, n) {
    cin >> s[i];
    RollingHash<char> rh(s[i]);
    v.emplace_back(rh);
  }
  map<pair<int, int>, int> cnt[26];
  rep(i, n) { cnt[s[i][0] - 'a'][v[i].get(1, (int)s[i].size())]++; }
  ll ans = 0;
  rep(i, n) {
    set<int> S;
    S.emplace(s[i][0] - 'a');
    int m = s[i].size();
    for (int j = 1; j <= m; j++) {
      for (int s : S) {
        ans += cnt[s][v[i].get(j, m)];
      }
      if (j == m)
        continue;
      S.emplace(s[i][j] - 'a');
    }
  }
  cout << ans - n << endl;
  return 0;
}