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

#include <bits/stdc++.h>

using namespace std;

const int N = 1000005;
const int pr[2] = {37, 1999};
const int md[2] = {(int)1e9 + 7, (int)1e9 + 9};
const int inf = 2e9;

int mark[N];
string a[N / 4];

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  multiset<long long> st;
  for (int i = 0; i < n; i++) {
    cin >> a[i];
    int hsh[2] = {0, 0};
    for (int t = (int)a[i].size() - 1; t >= 0; t--) {
      int c = a[i][t] - 'a' + 1;
      for (int j : {0, 1}) {
        hsh[j] = (1ll * hsh[j] * pr[j] + c) % md[j];
      }
    }
    long long ok = 1ll * hsh[0] * hsh[1];
    st.insert(ok);
  }
  long long res = 0;
  for (int it = 0; it < n; it++) {
    string s = a[it];
    int m = (int)s.size();
    mark[0] = 0;
    for (int i = 0; i < m; i++) {
      mark[i + 1] = mark[i] | (1 << (s[i] - 'a'));
    }
    if (m > 1) {
      while (mark[m] > 0) {
        int j = __builtin_ctz(mark[m] & -mark[m]);
        mark[m] -= 1 << j;
        int ok = (j + 1) * (j + 1);
        res += st.count(ok);
      }
    }
    int cur[2] = {0, 0};
    for (int i = m - 1; i > 1; i--) {
      for (int j : {0, 1}) {
        cur[j] = (1ll * cur[j] * pr[j] + (s[i] - 'a' + 1)) % md[j];
      }
      while (mark[i] > 0) {
        int j = __builtin_ctz(mark[i] & -mark[i]);
        mark[i] -= 1 << j;
        int need[2] = {0, 0};
        for (int k : {0, 1})
          need[k] = (1ll * cur[k] * pr[k] + j + 1) % md[k];
        long long ok = 1ll * need[0] * need[1];
        res += st.count(ok);
      }
    }
  }
  cout << res << '\\n';
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;

using namespace __gnu_pbds;

const int N = 1000005;
const int pr[2] = {37, 1999};
const int md[2] = {(int)1e9 + 7, (int)1e9 + 9};

gp_hash_table<long long, int> cnt;

int mark[N];
string a[N];

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    cin >> a[i];
    int hsh[2] = {0, 0};
    for (int t = (int)a[i].size() - 1; t >= 0; t--) {
      int c = a[i][t] - 'a' + 1;
      for (int j : {0, 1}) {
        hsh[j] = (1ll * hsh[j] * pr[j] + c) % md[j];
      }
    }
    long long need = 1ll * hsh[0] * md[1] + hsh[1];
    ++cnt[need];
  }
  long long res = 0;
  for (int it = 0; it < n; it++) {
    string s = a[it];
    int m = (int)s.size();
    mark[0] = 0;
    for (int i = 0; i < m; i++) {
      mark[i + 1] = mark[i] | (1 << (s[i] - 'a'));
    }
    if (m > 1) {
      for (int j = 0; j < 26; j++) {
        if ((mark[m] >> j) & 1) {
          long long need = 1ll * (j + 1) * md[1] + (j + 1);
          res += cnt[need];
        }
      }
    }
    int cur[2] = {0, 0};
    for (int i = m - 1; i > 1; i--) {
      for (int j : {0, 1}) {
        cur[j] = (1ll * cur[j] * pr[j] + (s[i] - 'a' + 1)) % md[j];
      }
      for (int j = 0; j < 26; j++) {
        if ((mark[i] >> j) & 1) {
          int need[2] = {0, 0};
          for (int k : {0, 1})
            need[k] = (1ll * cur[k] * pr[k] + j + 1) % md[k];
          long long ok = 1ll * need[0] * md[1] + need[1];
          res += cnt[ok];
        }
      }
    }
  }
  cout << res << '\\n';
  return 0;
}