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

#include <bits/stdc++.h>

using namespace std;

using int64 = long long;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << p.first << " " << p.second;
  return os;
}

template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template <typename T> istream &operator>>(istream &is, vector<T> &v) {
  for (T &in : v)
    is >> in;
  return is;
}

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) {
  return a < b && (a = b, true);
}

template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) {
  return a > b && (a = b, true);
}

template <typename T = int64> vector<T> make_v(size_t a) {
  return vector<T>(a);
}

template <typename T, typename... Ts> auto make_v(size_t a, Ts... ts) {
  return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template <typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type fill_v(T &t, const V &v) {
  t = v;
}

template <typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type fill_v(T &t, const V &v) {
  for (auto &e : t)
    fill_v(e, v);
}

template <typename F> struct FixPoint : F {
  FixPoint(F &&f) : F(forward<F>(f)) {}

  template <typename... Args> decltype(auto) operator()(Args &&...args) const {
    return F::operator()(*this, forward<Args>(args)...);
  }
};

template <typename F> inline decltype(auto) MFP(F &&f) {
  return FixPoint<F>{forward<F>(f)};
}

uint64_t power[1010101];
using uint128_t = __uint128_t;
static const uint64_t mod = (1ull << 61ull) - 1;

static inline uint64_t add(uint64_t a, uint64_t b) {
  if ((a += b) >= mod)
    a -= mod;
  return a;
}

static inline uint64_t mul(uint64_t a, uint64_t b) {
  uint128_t c = (uint128_t)a * b;
  return add(c >> 61, c & mod);
}

/**
 * @brief Rolling-Hash(ローリングハッシュ)
 * @see https://qiita.com/keymoon/items/11fac5627672a6d6a9f6
 * @docs docs/rolling-hash.md
 */
struct RollingHash {
  vector<uint64_t> hashed;
  const uint64_t base;

  static inline uint64_t generate_base() {
    mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
    uniform_int_distribution<uint64_t> rand(1, mod - 1);
    return rand(mt);
  }

  RollingHash() = default;

  RollingHash(const string &s, uint64_t base) : base(base) {
    size_t sz = s.size();
    hashed.assign(sz + 1, 0);
    for (int i = 0; i < sz; i++) {
      hashed[i + 1] = add(mul(hashed[i], base), s[i]);
    }
  }

  template <typename T>
  RollingHash(const vector<T> &s, uint64_t base) : base(base) {
    size_t sz = s.size();
    hashed.assign(sz + 1, 0);
    for (int i = 0; i < sz; i++) {
      hashed[i + 1] = add(mul(hashed[i], base), s[i]);
    }
  }

  uint64_t query(int l, int r) const {
    return add(hashed[r], mod - mul(hashed[l], power[r - l]));
  }

  uint64_t combine(uint64_t h1, uint64_t h2, size_t h2len) const {
    return add(mul(h1, power[h2len]), h2);
  }

  int lcp(const RollingHash &b, int l1, int r1, int l2, int r2) const {
    assert(base == b.base);
    int len = min(r1 - l1, r2 - l2);
    int low = 0, high = len + 1;
    while (high - low > 1) {
      int mid = (low + high) / 2;
      if (query(l1, l1 + mid) == b.query(l2, l2 + mid))
        low = mid;
      else
        high = mid;
    }
    return low;
  }
};

int main() {
  int N;
  cin >> N;
  vector<string> S(N);
  cin >> S;

  auto base = RollingHash::generate_base();

  power[0] = 1;
  for (int i = 0; i < 1010100; i++) {
    power[i + 1] = mul(power[i], base);
  }

  vector<uint64_t> vs;
  for (int i = 0; i < 26; i++) {
    string s;
    s += (char)(i + 'a');
    vs.emplace_back(RollingHash(s, base).query(0, 1));
  }

  map<uint64_t, int> mp[1010101];
  int64 ret = 0;
  vector<RollingHash> rols;
  for (int i = 0; i < N; i++) {
    rols.emplace_back(RollingHash(S[i], base));
    mp[S[i].size()][rols.back().query(0, S[i].size())]++;
  }
  for (int i = 0; i < N; i++) {
    auto &roll = rols[i];
    int ok = 0;
    for (int j = 0; j <= S[i].size(); j++) {
      if (j == S.size()) {
        for (int k = 0; k < 26; k++) {
          if ((ok >> k) & 1) {
            auto it = mp[S[i].size() - j + 1].find(vs[k]);
            if (it != end(mp[S[i].size() - j + 1]))
              ret += it->second;
          }
        }
      } else if (j > 0) {
        for (int k = 0; k < 26; k++) {
          if ((ok >> k) & 1) {
            auto it = mp[S[i].size() - j + 1].find(roll.combine(
                vs[k], roll.query(j, S[i].size()), S[i].size() - j));
            if (it != end(mp[S[i].size() - j + 1]))
              ret += it->second;
          }
        }
      } else {
        auto it = mp[S[i].size() - j + 1].find(roll.query(j, S[i].size()));
        if (it != end(mp[S[i].size() - j + 1]))
          ret += it->second;
      }
      if (j < S[i].size()) {
        ok |= 1 << (S[i][j] - 'a');
      }
    }
  }

  cout << ret - N << "\\n";
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

using int64 = long long;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << p.first << " " << p.second;
  return os;
}

template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template <typename T> istream &operator>>(istream &is, vector<T> &v) {
  for (T &in : v)
    is >> in;
  return is;
}

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) {
  return a < b && (a = b, true);
}

template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) {
  return a > b && (a = b, true);
}

template <typename T = int64> vector<T> make_v(size_t a) {
  return vector<T>(a);
}

template <typename T, typename... Ts> auto make_v(size_t a, Ts... ts) {
  return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template <typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type fill_v(T &t, const V &v) {
  t = v;
}

template <typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type fill_v(T &t, const V &v) {
  for (auto &e : t)
    fill_v(e, v);
}

template <typename F> struct FixPoint : F {
  FixPoint(F &&f) : F(forward<F>(f)) {}

  template <typename... Args> decltype(auto) operator()(Args &&...args) const {
    return F::operator()(*this, forward<Args>(args)...);
  }
};

template <typename F> inline decltype(auto) MFP(F &&f) {
  return FixPoint<F>{forward<F>(f)};
}

uint64_t power[1010101];
using uint128_t = __uint128_t;
static const uint64_t mod = (1ull << 61ull) - 1;

static inline uint64_t add(uint64_t a, uint64_t b) {
  if ((a += b) >= mod)
    a -= mod;
  return a;
}

static inline uint64_t mul(uint64_t a, uint64_t b) {
  uint128_t c = (uint128_t)a * b;
  return add(c >> 61, c & mod);
}

/**
 * @brief Rolling-Hash(ローリングハッシュ)
 * @see https://qiita.com/keymoon/items/11fac5627672a6d6a9f6
 * @docs docs/rolling-hash.md
 */
struct RollingHash {
  vector<uint64_t> hashed;
  const uint64_t base;

  static inline uint64_t generate_base() {
    mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
    uniform_int_distribution<uint64_t> rand(1, mod - 1);
    return rand(mt);
  }

  RollingHash() = default;

  RollingHash(const string &s, uint64_t base) : base(base) {
    size_t sz = s.size();
    hashed.assign(sz + 1, 0);
    for (int i = 0; i < sz; i++) {
      hashed[i + 1] = add(mul(hashed[i], base), s[i]);
    }
  }

  template <typename T>
  RollingHash(const vector<T> &s, uint64_t base) : base(base) {
    size_t sz = s.size();
    hashed.assign(sz + 1, 0);
    for (int i = 0; i < sz; i++) {
      hashed[i + 1] = add(mul(hashed[i], base), s[i]);
    }
  }

  uint64_t query(int l, int r) const {
    return add(hashed[r], mod - mul(hashed[l], power[r - l]));
  }

  uint64_t combine(uint64_t h1, uint64_t h2, size_t h2len) const {
    return add(mul(h1, power[h2len]), h2);
  }

  int lcp(const RollingHash &b, int l1, int r1, int l2, int r2) const {
    assert(base == b.base);
    int len = min(r1 - l1, r2 - l2);
    int low = 0, high = len + 1;
    while (high - low > 1) {
      int mid = (low + high) / 2;
      if (query(l1, l1 + mid) == b.query(l2, l2 + mid))
        low = mid;
      else
        high = mid;
    }
    return low;
  }
};

int main() {
  int N;
  cin >> N;
  vector<string> S(N);
  cin >> S;

  auto base = RollingHash::generate_base();

  power[0] = 1;
  for (int i = 0; i < 1010100; i++) {
    power[i + 1] = mul(power[i], base);
  }

  vector<uint64_t> vs;
  for (int i = 0; i < 26; i++) {
    string s;
    s += (char)(i + 'a');
    vs.emplace_back(RollingHash(s, base).query(0, 1));
  }

  map<uint64_t, int> mp[1010101];
  int64 ret = 0;
  vector<RollingHash> rols;
  for (int i = 0; i < N; i++) {
    rols.emplace_back(RollingHash(S[i], base));
    mp[S[i].size()][rols.back().query(0, S[i].size())]++;
  }
  for (int i = 0; i < N; i++) {
    auto &roll = rols[i];
    int ok = 0;
    for (int j = 0; j <= S[i].size(); j++) {
      if (j == S.size()) {
        for (int k = 0; k < 26; k++) {
          if ((ok >> k) & 1) {
            ret += mp[S[i].size() - j + 1][vs[k]];
          }
        }
      } else if (j > 0) {
        for (int k = 0; k < 26; k++) {
          if ((ok >> k) & 1) {
            ret += mp[S[i].size() - j + 1][roll.combine(
                vs[k], roll.query(j, S[i].size()), S[i].size() - j)];
          }
        }
      } else {
        ret += mp[S[i].size() - j + 1][roll.query(j, S[i].size())];
      }
      if (j < S[i].size()) {
        ok |= 1 << (S[i][j] - 'a');
      }
    }
  }

  cout << ret - N << "\\n";
}