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

#include <algorithm>
#include <array>
#include <assert.h>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;

#define ALL(c) (c).begin(), (c).end()
#define PB push_back
#define IN(x, c) (find(c.begin(), c.end(), x) != (c).end())
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define INIT(a, v) memset(a, v, sizeof(a))
#define SORT_UNIQUE(c)                                                         \\
  (sort(c.begin(), c.end()),                                                   \\
   c.resize(distance(c.begin(), unique(c.begin(), c.end()))))
template <class A, class B> A cvt(B x) {
  stringstream ss;
  ss << x;
  A y;
  ss >> y;
  return y;
}

#define SPC << " " <<
#define DEBUG(x)                                                               \\
  cerr << #x << " = ";                                                         \\
  cerr << x << endl;
#define DEBUG_ITER(x)                                                          \\
  cerr << #x << " = ";                                                         \\
  for (auto _ : x)                                                             \\
    cerr << _ << ' ';                                                          \\
  cerr << endl;

typedef pair<int, int> PII;
typedef long long int64;
typedef vector<int> VI;

bool cmpLen(const string &s1, const string &s2) {
  return s1.size() < s2.size();
}

unordered_map<int64, int> f;
int ch[30];

void gen() {
  srand(time(0));
  int n = 1000;
  set<string> ss;
  REP(i, n) {
    int len = 1 + rand() % 2000;
    string s;
    REP(i, len) { s += 'a' + rand() % 20; }
    ss.insert(s);
  }
  cout << ss.size() << endl;
  int total = 0;
  for (string s : ss) {
    cout << s << endl;
    total += s.size();
  }
  cerr << total << endl;
}

int main() {
  // freopen("test.in","w",stdout); gen(); return 0;
  // freopen("test.in","r",stdin);
  int n;
  cin >> n;
  vector<string> ss(n);
  int64 total = 0;
  REP(i, n) {
    cin >> ss[i];
    total += ss[i].size();
  }
  f.reserve(total);
  sort(ALL(ss), cmpLen);
  int64 r = 0;
  for (string s : ss) {
    int64 h = 0;
    int64 p = 90000000000077LL;
    // query
    INIT(ch, 0);
    REP(i, s.size()) ch[s[i] - 'a' + 1]++;
    h = 0;
    for (int i = s.size() - 1; i >= 0; i--) {
      REP(c, 30) if (ch[c]) {
        int64 k = (h * 31 + c) % p;
        if (f.count(k))
          r += f[k];
      }
      h = (h * 31 + (s[i] - 'a' + 1)) % p;
      ch[s[i] - 'a' + 1]--;
    }
    // update
    h = 0;
    for (int i = s.size() - 1; i >= 0; i--) {
      h = (h * 31 + (s[i] - 'a' + 1)) % p;
    }
    f[h]++;
  }
  cout << r << endl;
  /*int q=0;
  for (int i=0;i<n;i++) {
          //cout << ss[i] << endl;
          for (int j=0;j<n;j++) if (i!=j && ss[i].size()<ss[j].size()) {
                  int match=1;
                  for (int k=0;k<ss[i].size()-1;k++) {
                          if (ss[i][ss[i].size()-1-k]!=ss[j][ss[j].size()-1-k])
  match=0;
                  }
                  int ch=0;
                  for (int k=ss[j].size()-ss[i].size();k>=0;k--) {
                          if (ss[j][k]==ss[i][0]) ch=1;
                  }
                  if (match && ch) {
                          q++;
                  }
          }
  }
  cout << q << endl;*/
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <array>
#include <assert.h>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;

#define ALL(c) (c).begin(), (c).end()
#define PB push_back
#define IN(x, c) (find(c.begin(), c.end(), x) != (c).end())
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define INIT(a, v) memset(a, v, sizeof(a))
#define SORT_UNIQUE(c)                                                         \\
  (sort(c.begin(), c.end()),                                                   \\
   c.resize(distance(c.begin(), unique(c.begin(), c.end()))))
template <class A, class B> A cvt(B x) {
  stringstream ss;
  ss << x;
  A y;
  ss >> y;
  return y;
}

#define SPC << " " <<
#define DEBUG(x)                                                               \\
  cerr << #x << " = ";                                                         \\
  cerr << x << endl;
#define DEBUG_ITER(x)                                                          \\
  cerr << #x << " = ";                                                         \\
  for (auto _ : x)                                                             \\
    cerr << _ << ' ';                                                          \\
  cerr << endl;

typedef pair<int, int> PII;
typedef long long int64;
typedef vector<int> VI;

bool cmpLen(const string &s1, const string &s2) {
  return s1.size() < s2.size();
}

unordered_map<int64, int> f;
int ch[30];

void gen() {
  srand(time(0));
  int n = 1000;
  set<string> ss;
  REP(i, n) {
    int len = 1 + rand() % 20;
    string s;
    REP(i, len) { s += 'a' + rand() % 3; }
    ss.insert(s);
  }
  cout << ss.size() << endl;
  for (string s : ss)
    cout << s << endl;
}

int main() {
  // freopen("test.in","w",stdout); gen(); return 0;
  // freopen("test.in","r",stdin);
  int n;
  cin >> n;
  vector<string> ss(n);
  REP(i, n) { cin >> ss[i]; }
  f.reserve(n * 31);
  sort(ALL(ss), cmpLen);
  reverse(ALL(ss));
  int64 r = 0;
  for (string s : ss) {
    int64 h = 0;
    int64 p = 90000000000077LL;
    // query
    for (int i = s.size() - 1; i >= 1; i--) {
      h = (h * 31 + (s[i] - 'a' + 1)) % p;
    }
    r += f[h * 100 + s[0] - 'a' + 1];
    // update
    INIT(ch, 0);
    ch[0] = 1;
    REP(i, s.size()) ch[s[i] - 'a' + 1]++;
    h = 0;
    for (int i = s.size() - 1; i >= 0; i--) {
      REP(c, 30) if (ch[c]) { f[h * 100 + c]++; }
      h = (h * 31 + (s[i] - 'a' + 1)) % p;
      ch[s[i] - 'a' + 1]--;
    }
    f[h * 100 + 0]++;
  }
  cout << r << endl;
  /*int q=0;
  for (int i=0;i<n;i++) {
          //cout << ss[i] << endl;
          for (int j=0;j<n;j++) if (i!=j && ss[i].size()<ss[j].size()) {
                  int match=1;
                  for (int k=0;k<ss[i].size()-1;k++) {
                          if (ss[i][ss[i].size()-1-k]!=ss[j][ss[j].size()-1-k])
  match=0;
                  }
                  int ch=0;
                  for (int k=ss[j].size()-ss[i].size();k>=0;k--) {
                          if (ss[j][k]==ss[i][0]) ch=1;
                  }
                  if (match && ch) {
                          q++;
                  }
          }
  }
  cout << q << endl;*/
  return 0;
}