Problem p02589 (C++) — buggy submission, verdict: Runtime Error

#ifdef LOCAL
#define _GLIBCXX_DEBUG
#define __clock__
#else
#pragma GCC optimize("Ofast")
#endif
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using VI = vector<ll>;
using VV = vector<VI>;
using VS = vector<string>;
using PII = pair<ll, ll>;

// tourist set
template <typename A, typename B> string to_string(pair<A, B> p);

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);

string to_string(const string &s) { return '"' + s + '"'; }

string to_string(const char *s) { return to_string((string)s); }

string to_string(bool b) { return (b ? "true" : "false"); }

string to_string(vector<bool> v) {
  bool first = true;
  string res = "{";
  for (int i = 0; i < static_cast<int>(v.size()); i++) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(v[i]);
  }
  res += "}";
  return res;
}

template <size_t N> string to_string(bitset<N> v) {
  string res = "";
  for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
  }
  return res;
}

template <typename A> string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto &x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}

template <typename A, typename B> string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ")";
}

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}

void debug_out() { cerr << '\\n'; }

template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}

#ifdef LOCAL
#define debug(...) 42
// #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:",
// debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
// tourist set end

template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

#define FOR(i, a, b) for (ll i = (a); i < (b); ++i)
#define rep(i, b) FOR(i, 0, b)
#define ALL(v) (v).begin(), (v).end()
#define p(s) cout << (s) << '\\n'
#define p2(s, t) cout << (s) << " " << (t) << '\\n'
#define br() p("")
#define pn(s) cout << (#s) << " " << (s) << '\\n'
#define SZ(x) ((int)(x).size())
#define SORT(A) sort(ALL(A))
#define RSORT(A) sort(ALL(A), greater<ll>())
#define MP make_pair
#define p_yes() p("YES")
#define p_no() p("NO")

ll SUM(VI &V) { return accumulate(ALL(V), 0LL); }

ll MIN(VI &V) { return *min_element(ALL(V)); }
ll MAX(VI &V) { return *max_element(ALL(V)); }

void print_vector(VI &V) {
  ll n = V.size();
  rep(i, n) {
    if (i)
      cout << ' ';
    cout << V[i];
  }
  cout << endl;
}

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

ll lcm(ll a, ll b) {
  ll g = gcd(a, b);
  return a / g * b;
}

// long double
using ld = long double;
#define EPS (1e-14)
#define equals(a, b) (fabs((a) - (b)) < EPS)

void no() {
  p_no();
  exit(0);
}
void yes() {
  p_yes();
  exit(0);
}

const ll mod = 1e9 + 7;
const ll inf = 1e18;
const double PI = acos(-1);

// snuke's mint
// auto mod int
// https://youtu.be/L8grWxBlIZ4?t=9858
// https://youtu.be/ERZuLAxZffQ?t=4807 : optimize
// https://youtu.be/8uowVvQ_-Mo?t=1329 : division
// const int mod = 1000000007;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const {
    mint res(*this);
    return res += a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res -= a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res *= a;
  }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return (*this) *= a.inv(); }
  mint operator/(const mint a) const {
    mint res(*this);
    return res /= a;
  }
};

template <unsigned mod> struct RollingHash {
  vector<unsigned> hashed, power;

  inline unsigned mul(unsigned a, unsigned b) const {
    unsigned long long x = (unsigned long long)a * b;
    unsigned xh = (unsigned)(x >> 32), xl = (unsigned)x, d, m;
    asm("divl %4; \\n\\t" : "=a"(d), "=d"(m) : "d"(xh), "a"(xl), "r"(mod));
    return m;
  }

  RollingHash() {}

  RollingHash(const string &s, unsigned base = 10007) {
    // RollingHash(const string &s, unsigned base = 1e9+7) {
    int sz = (int)s.size();
    hashed.assign(sz + 1, 0);
    power.assign(sz + 1, 0);
    power[0] = 1;
    for (int i = 0; i < sz; i++) {
      power[i + 1] = mul(power[i], base);
      hashed[i + 1] = mul(hashed[i], base) + s[i];
      if (hashed[i + 1] >= mod)
        hashed[i + 1] -= mod;
    }
  }

  unsigned get(int l, int r) const {
    unsigned ret = hashed[r] + mod - mul(hashed[l], power[r - l]);
    if (ret >= mod)
      ret -= mod;
    return ret;
  }

  unsigned connect(unsigned h1, int h2, int h2len) const {
    unsigned ret = mul(h1, power[h2len]) + h2;
    if (ret >= mod)
      ret -= mod;
    return ret;
  }

  int LCP(const RollingHash<mod> &b, int l1, int r1, int l2, int r2) {
    int len = min(r1 - l1, r2 - l2);
    int low = -1, high = len + 1;
    while (high - low > 1) {
      int mid = (low + high) / 2;
      if (get(l1, l1 + mid) == b.get(l2, l2 + mid))
        low = mid;
      else
        high = mid;
    }
    return (low);
  }
};

// 1029392827
// 1000000007
using RH = RollingHash<998244353>;
using RH2 = RollingHash<924844033>;

// super rolling hash
struct SRH {
  RH rh;
  RH2 rh2;
  SRH() {}
  SRH(const string &s) {
    rh = RH(s);
    rh2 = RH2(s);
  }

  ll get(ll l, ll r) { return rh.get(l, r) + 1e9 * rh2.get(l, r); }
};

// できること
// 一点追加
// 範囲和
// ei1333's BIT
struct BIT {
  VI data;

  BIT(ll sz) { data.assign(++sz, 0); }

  ll sum(ll k) {
    ll ret = 0;
    for (++k; k > 0; k -= k & -k)
      ret += data[k];
    return (ret);
  }

  // [i, j]
  ll range_sum(ll i, ll j) {
    if (i == 0) {
      return sum(j);
    } else {
      return sum(j) - sum(i - 1);
    }
  }

  void add(ll k, ll x) {
    for (++k; k < SZ(data); k += k & -k)
      data[k] += x;
  }
};

struct Hoge {
  vector<BIT> bits;

  Hoge(string &s) {
    ll N = s.size();
    rep(i, 26) {
      auto bi = BIT(N);
      bits.push_back(bi);
    }
    rep(i, N) {
      ll v = s[i] - 'a';
      bits[v].add(i, 1);
    }
  }

  ll range_count(ll l, ll r, char c) {
    ll v = c - 'a';
    return bits[v].range_sum(l, r);
  }
};

bool comp(const std::string &lh, const std::string &rh) {
  // 文字列lhの長さが文字列rhより短かったらtrueを返す
  return lh.length() < rh.length();
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  // input
  ll N;
  cin >> N;

  VS S(N);
  rep(i, N) {
    string s;
    cin >> s;
    // reverse(ALL(s));
    S[i] = s;
  }
  sort(ALL(S), comp);
  debug(S);

  // map<char,ll> mp_one;
  // for(string s : S){
  //   set<char> se;
  //   for(char c : s) se.insert(c);
  //   for(char c : se){
  //     mp_one[c]++;
  //   }
  // }

  ll cnt = 0;
  // (char, hash) => count
  map<pair<char, ll>, ll> mp;
  {
    for (string s : S) {
      // cerr<<endl;
      debug(s);

      ll L = SZ(s);
      auto rh = SRH(s);

      auto hoge = Hoge(s);

      if (L == 1) {
        // char c = s[0];
        // cnt += mp_one[c]-1;
        // debug("easy", s, mp_one[c]-1);
        // continue;

        // 登録だけしておく
        auto key = make_pair(s[0], 0);
        mp[key]++;
        continue;
      }

      ll null_hash = -1;

      // 長さ１のやつとのマッチング
      {
        set<char> se;
        for (char c : s)
          se.insert(c);
        for (char c : se) {
          auto key = make_pair(c, 0);
          if (mp.count(key))
            cnt++;
        }
      }

      // 探す
      if (L > 1) {
        FOR(i, 1, L) {
          // i以降をtail
          ll tail_hash = rh.get(i, L);

          debug("[search] tail", s.substr(i, L - i));

          // それ以外の左の部分について
          // 遅いVer
          // set<char> se;
          // FOR(j,0,i) se.insert(s[j]); // O(L)
          // for(char c : se){
          //   auto key = make_pair(c, tail_hash);
          //   if(mp.count(key)){
          //     debug("hit!", s, i, mp[key]);
          //     cnt += mp[key];
          //   }
          // }

          // 速いVer
          // 0 to i-1までにcがあればいい
          rep(j, 26) {
            char c = j + 'a';
            if (hoge.range_count(0, i - 1, c)) {
              auto key = make_pair(c, tail_hash);
              if (mp.count(key)) {
                debug("hit!", s, i, mp[key]);
                cnt += mp[key];
              }
            }
          }
        }
      }

      // 自身を登録
      ll tail_hash = rh.get(1, L);
      auto key = make_pair(s[0], tail_hash);
      // cerr << "[register] head " << s[0] << " hash " << tail_hash << endl;
      mp[key]++;
    }
  }

  p(cnt);

  // vector<RH> R;
  // rep(i,N){
  //   auto ro = RH(S[i]);
  //   R.push_back(ro);
  // }

  // map<char,ll> mp;
  // for(string s : S){
  //   set<char> se;
  //   for(char c : s) se.insert(c);
  //   for(char c : se){
  //     mp[c]++;
  //   }
  // }

  // // debug(R[0].get(0,1));
  // // debug(R[1].get(0,1));

  // // {
  // //   string a = "xxxabcxxx";
  // //   string b = "zabczzzzz";
  // //   auto ha = RH(a);
  // //   auto hb = RH(b);
  // //   debug(ha.get(3,5));
  // //   debug(hb.get(1,3));
  // //   exit(0);
  // // }

  // vector<Hoge> H;
  // rep(i,N){
  //   auto ho = Hoge(S[i]);
  //   H.push_back(ho);
  // }

  // ll cnt=0;
  // rep(i,N){
  //   cerr<<endl;
  //   debug(i,S[i]);
  //   string s = S[i];
  //   ll L = s.size();

  //   if(L==1){
  //     char c = s[0];
  //     cnt += mp[c]-1;
  //     debug("easy", s, mp[c]-1);
  //     continue;
  //   }

  //   // L>=2
  //   ll head_hash = R[i].get(0,L-2); // head hashが一致するなら候補
  //   debug(head_hash);
  //   char tail_char = s.back(); // ひだり
  //   //cerr << "tail char " << tail_char << endl;

  //   FOR(j,i+1,N){

  //     if(S[j].size()<=S[i].size()) break;
  //     if(S[j][0]!=S[i][0]) break;
  //     if(R[j].get(0,L-2)==head_hash){
  //       // 確認
  //       if(s.substr(0,L-2+1) != S[j].substr(0,L-2+1)) break;
  //       debug("tail same", S[j]);
  //       debug(L-1,SZ(S[j])-1);
  //       if(H[j].range_count(L-1, SZ(S[j])-1, tail_char)){
  //         debug("plus");
  //         cnt++;
  //       }
  //     }
  //     else{
  //       break;
  //     }
  //   }
  // }
  // p(cnt);
  return 0;
}

Error: 0

Fixed submission:

#ifdef LOCAL
#define _GLIBCXX_DEBUG
#define __clock__
#else
#pragma GCC optimize("Ofast")
#endif
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using VI = vector<ll>;
using VV = vector<VI>;
using VS = vector<string>;
using PII = pair<ll, ll>;

// tourist set
template <typename A, typename B> string to_string(pair<A, B> p);

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);

string to_string(const string &s) { return '"' + s + '"'; }

string to_string(const char *s) { return to_string((string)s); }

string to_string(bool b) { return (b ? "true" : "false"); }

string to_string(vector<bool> v) {
  bool first = true;
  string res = "{";
  for (int i = 0; i < static_cast<int>(v.size()); i++) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(v[i]);
  }
  res += "}";
  return res;
}

template <size_t N> string to_string(bitset<N> v) {
  string res = "";
  for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
  }
  return res;
}

template <typename A> string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto &x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}

template <typename A, typename B> string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ")";
}

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}

void debug_out() { cerr << '\\n'; }

template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}

#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
// tourist set end

template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

#define FOR(i, a, b) for (ll i = (a); i < (b); ++i)
#define rep(i, b) FOR(i, 0, b)
#define ALL(v) (v).begin(), (v).end()
#define p(s) cout << (s) << '\\n'
#define p2(s, t) cout << (s) << " " << (t) << '\\n'
#define br() p("")
#define pn(s) cout << (#s) << " " << (s) << '\\n'
#define SZ(x) ((int)(x).size())
#define SORT(A) sort(ALL(A))
#define RSORT(A) sort(ALL(A), greater<ll>())
#define MP make_pair
#define p_yes() p("YES")
#define p_no() p("NO")

ll SUM(VI &V) { return accumulate(ALL(V), 0LL); }

ll MIN(VI &V) { return *min_element(ALL(V)); }
ll MAX(VI &V) { return *max_element(ALL(V)); }

void print_vector(VI &V) {
  ll n = V.size();
  rep(i, n) {
    if (i)
      cout << ' ';
    cout << V[i];
  }
  cout << endl;
}

ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

ll lcm(ll a, ll b) {
  ll g = gcd(a, b);
  return a / g * b;
}

// long double
using ld = long double;
#define EPS (1e-14)
#define equals(a, b) (fabs((a) - (b)) < EPS)

void no() {
  p_no();
  exit(0);
}
void yes() {
  p_yes();
  exit(0);
}

const ll mod = 1e9 + 7;
const ll inf = 1e18;
const double PI = acos(-1);

// snuke's mint
// auto mod int
// https://youtu.be/L8grWxBlIZ4?t=9858
// https://youtu.be/ERZuLAxZffQ?t=4807 : optimize
// https://youtu.be/8uowVvQ_-Mo?t=1329 : division
// const int mod = 1000000007;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator-=(const mint a) {
    if ((x += mod - a.x) >= mod)
      x -= mod;
    return *this;
  }
  mint &operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const {
    mint res(*this);
    return res += a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res -= a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res *= a;
  }
  mint pow(ll t) const {
    if (!t)
      return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1)
      a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint a) { return (*this) *= a.inv(); }
  mint operator/(const mint a) const {
    mint res(*this);
    return res /= a;
  }
};

template <unsigned mod> struct RollingHash {
  vector<unsigned> hashed, power;

  inline unsigned mul(unsigned a, unsigned b) const {
    unsigned long long x = (unsigned long long)a * b;
    unsigned xh = (unsigned)(x >> 32), xl = (unsigned)x, d, m;
    asm("divl %4; \\n\\t" : "=a"(d), "=d"(m) : "d"(xh), "a"(xl), "r"(mod));
    return m;
  }

  // RollingHash(){

  // }

  RollingHash(const string &s, unsigned base = 10007) {
    int sz = (int)s.size();
    hashed.assign(sz + 1, 0);
    power.assign(sz + 1, 0);
    power[0] = 1;
    for (int i = 0; i < sz; i++) {
      power[i + 1] = mul(power[i], base);
      hashed[i + 1] = mul(hashed[i], base) + s[i];
      if (hashed[i + 1] >= mod)
        hashed[i + 1] -= mod;
    }
  }

  unsigned get(int l, int r) const {
    unsigned ret = hashed[r] + mod - mul(hashed[l], power[r - l]);
    if (ret >= mod)
      ret -= mod;
    return ret;
  }

  unsigned connect(unsigned h1, int h2, int h2len) const {
    unsigned ret = mul(h1, power[h2len]) + h2;
    if (ret >= mod)
      ret -= mod;
    return ret;
  }

  int LCP(const RollingHash<mod> &b, int l1, int r1, int l2, int r2) {
    int len = min(r1 - l1, r2 - l2);
    int low = -1, high = len + 1;
    while (high - low > 1) {
      int mid = (low + high) / 2;
      if (get(l1, l1 + mid) == b.get(l2, l2 + mid))
        low = mid;
      else
        high = mid;
    }
    return (low);
  }
};

using RH = RollingHash<1000000007>;

// できること
// 一点追加
// 範囲和
// ei1333's BIT
struct BIT {
  VI data;

  BIT(ll sz) { data.assign(++sz, 0); }

  ll sum(ll k) {
    ll ret = 0;
    for (++k; k > 0; k -= k & -k)
      ret += data[k];
    return (ret);
  }

  // [i, j]
  ll range_sum(ll i, ll j) {
    if (i == 0) {
      return sum(j);
    } else {
      return sum(j) - sum(i - 1);
    }
  }

  void add(ll k, ll x) {
    for (++k; k < data.size(); k += k & -k)
      data[k] += x;
  }
};

struct Hoge {
  vector<BIT> bits;

  Hoge(string &s) {
    ll N = s.size();
    rep(i, 26) {
      auto bi = BIT(N);
      bits.push_back(bi);
    }
    rep(i, N) {
      ll v = s[i] - 'a';
      bits[v].add(i, 1);
    }
  }

  ll range_count(ll l, ll r, char c) {
    ll v = c - 'a';
    return bits[v].range_sum(l, r);
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  // input
  ll N;
  cin >> N;

  // if(N>500){
  //   assert(1==2);
  // }

  VS S(N);
  rep(i, N) {
    cin >> S[i];
    if (SZ(S[i]) == 1) {
      assert(1 == 2);
    }
  }

  // sからtは作れるか
  auto f = [&](string s, string t) {
    if (t.size() == 1) {
      char ch = t[0];
      for (char c : s) {
        if (c == ch)
          return true;
      }
      return false;
    }

    if (SZ(s) <= SZ(t))
      return false;

    ll sL = SZ(s);
    ll tL = SZ(t);

    // |t|>1
    // しっぽは同じ
    string tail = t.substr(1);
    ll tailL = SZ(tail);
    if (s.substr(sL - tailL) != tail)
      return false;
    char head = t[0];
    rep(i, sL - tailL) {
      if (s[i] == head)
        return true;
    }
    return false;
  };

  ll cnt = 0;
  rep(i, N) {
    rep(j, N) {
      if (i == j)
        continue;
      if (f(S[i], S[j])) {
        debug(S[i], S[j]);
        cnt++;
      }
    }
  }
  p(cnt);

  return 0;
}