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

#include <bits/stdc++.h>
// #pragma GCC target ("avx")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")
using namespace std;
#define int long long
#define rep(i, n) for (int i = 0; i < n; i++)
#define REP(i, n) for (int i = 1; i < n; i++)
#define rev(i, n) for (int i = n - 1; i >= 0; i--)
#define all(v) v.begin(), v.end()
#define P pair<int, int>
#define len(s) (int)s.size()

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
constexpr int mod = 1e9 + 7;
constexpr long long inf = 3e18;

template <class T> struct RollingHash {
  int Base = 283;
  const int MOD1 = 1e9 + 7, MOD2 = 1e9 + 9;
  vector<int> hash1, hash2, power1, power2;
  RollingHash(T s) {
    int sz = s.size();
    hash1.resize(sz + 1, 0);
    hash2.resize(sz + 1, 0);
    power1.resize(sz + 1, 1);
    power2.resize(sz + 1, 1);
    rep(i, sz) {
      hash1[i + 1] = (hash1[i] * Base + s[i]) % MOD1;
      hash2[i + 1] = (hash2[i] * Base + s[i]) % MOD2;
      power1[i + 1] = power1[i] * Base % MOD1;
      power2[i + 1] = power2[i] * Base % MOD2;
    }
  }
  P get(int l, int r) {
    return P((hash1[r] - hash1[l] * power1[r - l] + MOD1) % MOD1,
             (hash2[r] - hash2[l] * power2[r - l] + MOD2) % MOD2);
  }
  int lcp(int x, int y) {
    int len = min(hash1.size() - 1 - y, hash1.size() - 1 - x);
    int ok = 0, ng = len + 1;
    while (ng - ok > 1) {
      int mid = (ok + ng) / 2;
      if (get(x, x + mid) == get(y, y + mid))
        ok = mid;
      else
        ng = mid;
    }
    return ok;
  }
};

int N;
string S[200005];
signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin >> N;
  rep(i, N) {
    cin >> S[i];
    reverse(all(S[i]));
  }
  map<P, int> has;
  int ans = 0;
  int cnt[26];
  rep(i, N) {
    RollingHash<string> RH(S[i]);
    has[P(RH.hash1[len(S[i])], RH.hash2[len(S[i])])]++;
  }
  rep(i, N) {
    RollingHash<string> RH(S[i]);
    memset(cnt, 0, sizeof(cnt));
    for (char c : S[i])
      cnt[c - 'a']++;
    rep(j, 26) if (cnt[j]) {
      P p = P((int)('a') + j, (int)('a' + j));
      if (has.find(p) != has.end())
        ans += has[p];
    }
    rep(j, len(S[i])) {
      cnt[S[i][j] - 'a']--;
      rep(k, 26) {
        if (cnt[k]) {
          int m1 = (RH.hash1[j + 1] * RH.Base + (int)('a' + k)) % RH.MOD1;
          int m2 = (RH.hash2[j + 1] * RH.Base + (int)('a' + k)) % RH.MOD2;
          if (has.find(P(m1, m2)) != has.end())
            ans += has[P(m1, m2)];
        }
      }
    }
  }
  cout << ans - N << endl;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#pragma GCC target("avx")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")
using namespace std;
#define int long long
#define rep(i, n) for (int i = 0; i < n; i++)
#define REP(i, n) for (int i = 1; i < n; i++)
#define rev(i, n) for (int i = n - 1; i >= 0; i--)
#define all(v) v.begin(), v.end()
#define P pair<int, int>
#define len(s) (int)s.size()

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
constexpr int mod = 1e9 + 7;
constexpr long long inf = 3e18;

template <class T> struct RollingHash {
  int Base = 283;
  const int MOD1 = 1e9 + 7, MOD2 = 1e9 + 9;
  vector<int> hash1, hash2, power1, power2;
  RollingHash(T s) {
    int sz = s.size();
    hash1.resize(sz + 1, 0);
    hash2.resize(sz + 1, 0);
    power1.resize(sz + 1, 1);
    power2.resize(sz + 1, 1);
    rep(i, sz) {
      hash1[i + 1] = (hash1[i] * Base + s[i]) % MOD1;
      hash2[i + 1] = (hash2[i] * Base + s[i]) % MOD2;
      power1[i + 1] = power1[i] * Base % MOD1;
      power2[i + 1] = power2[i] * Base % MOD2;
    }
  }
  P get(int l, int r) {
    return P((hash1[r] - hash1[l] * power1[r - l] + MOD1) % MOD1,
             (hash2[r] - hash2[l] * power2[r - l] + MOD2) % MOD2);
  }
  int lcp(int x, int y) {
    int len = min(hash1.size() - 1 - y, hash1.size() - 1 - x);
    int ok = 0, ng = len + 1;
    while (ng - ok > 1) {
      int mid = (ok + ng) / 2;
      if (get(x, x + mid) == get(y, y + mid))
        ok = mid;
      else
        ng = mid;
    }
    return ok;
  }
};

int N;
string S[200005];
signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin >> N;
  rep(i, N) {
    cin >> S[i];
    reverse(all(S[i]));
  }
  map<P, int> has;
  int ans = 0;
  int cnt[26];
  rep(i, N) {
    RollingHash<string> RH(S[i]);
    has[P(RH.hash1[len(S[i])], RH.hash2[len(S[i])])]++;
  }
  rep(i, N) {
    RollingHash<string> RH(S[i]);
    memset(cnt, 0, sizeof(cnt));
    for (char c : S[i])
      cnt[c - 'a']++;
    rep(j, 26) if (cnt[j]) ans += has[P((int)('a') + j, (int)('a' + j))];
    rep(j, len(S[i])) {
      cnt[S[i][j] - 'a']--;
      rep(k, 26) {
        if (cnt[k]) {
          int m1 = (RH.hash1[j + 1] * RH.Base + (int)('a' + k)) % RH.MOD1;
          int m2 = (RH.hash2[j + 1] * RH.Base + (int)('a' + k)) % RH.MOD2;
          ans += has[P(m1, m2)];
        }
      }
    }
  }
  cout << ans - N << endl;
}