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

#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = a; i < (int)b; i++)
#define rep(i, n) REP(i, 0, n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a)                                                               \\
  { cout << #a << " = " << a << endl; }
template <class T1, class T2> inline bool minimize(T1 &a, T2 b) {
  return b < a && (a = b, 1);
}
template <class T1, class T2> inline bool maximize(T1 &a, T2 b) {
  return a < b && (a = b, 1);
}

typedef long long ll;

ll fact[13];
int sizes[1 << 12];

int main() {

  fact[0] = 1;
  REP(i, 1, 13) fact[i] = fact[i - 1] * i;

  for (int N, M; cin >> N >> M && (N | M);) {
    vector<string> vs;
    map<string, int> mp;
    rep(i, N) {
      string s;
      cin >> s;
      mp[s]++;
      vs.push_back(s);
    }

    rep(i, 1 << N) sizes[i] = 0;
    rep(S, 1 << N) {
      rep(i, N) {
        if (S >> i & 1)
          continue;
        sizes[S | (1 << i)] += vs[i].size();
      }
    }

    string T;
    rep(i, M) {
      char s[5001];
      cin >> s, T += s;
    }

    int TSize = T.size();

    ll sum = 0;
    rep(st, TSize - sizes[(1 << N) - 1] + 1) {
      ll dp[1 << N];
      memset(dp, 0, sizeof dp);
      dp[0] = 1;
      rep(S, 1 << N) {
        if (!dp[S])
          continue;
        rep(i, N) {
          if (S >> i & 1)
            continue;
          if (!T.compare(st + sizes[S], sizes[S | (1 << i)] - sizes[S],
                         vs[i])) {
            dp[S | (1 << i)] = 1;
          }
        }
      }
      sum += dp[(1 << N) - 1];
    }

    cout << sum << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = a; i < (int)b; i++)
#define rep(i, n) REP(i, 0, n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a)                                                               \\
  { cout << #a << " = " << a << endl; }
template <class T1, class T2> inline bool minimize(T1 &a, T2 b) {
  return b < a && (a = b, 1);
}
template <class T1, class T2> inline bool maximize(T1 &a, T2 b) {
  return a < b && (a = b, 1);
}

typedef long long ll;
int const inf = 1 << 29;

inline long long to_int64(char x) { return (long long)x; }

struct RollingHash {

  const array<int, 2> mods = {
      {int(1e9 + 7), int(1e9 + 9)}};       //, int(1234567891)}};
  const array<int, 2> Ks = {{1007, 1009}}; //, 1013}};
  const int ModsSize = mods.size();

  int N;
  string S;
  vector<vector<long long>> hash;
  vector<vector<long long>> pow_table;

  void construct() {
    hash.resize(ModsSize);
    int n = S.size();
    rep(i, ModsSize) hash[i].resize(n + 1);
    rep(i, ModsSize) {
      for (int j = n - 1; j >= 0; j--) {
        hash[i][j] = hash[i][j + 1] * Ks[i];
        hash[i][j] += to_int64(S[j]);
        hash[i][j] %= mods[i];
      }
    }

    pow_table.resize(ModsSize);
    rep(i, ModsSize) pow_table[i].resize(n + 1);

    rep(i, ModsSize) {
      pow_table[i][0] = 1;
      REP(j, 1, n + 1) {
        pow_table[i][j] = (pow_table[i][j - 1] * Ks[i]) % mods[i];
      }
    }
  }

  RollingHash(string const &s) {
    S = s;
    N = s.size();
    construct();
  }

  long long get_hash(int t, int start, int end) const {
    auto r = hash[t][start] - hash[t][end] * pow_table[t][end - start];
    r %= mods[t];
    if (r < 0) {
      r += mods[t];
    }
    return r;
  }

  bool same(int a_start, int a_end, int b_start, int b_end,
            RollingHash const &rh) const {
    int const len = a_end - a_start;
    if (len != b_end - b_start) {
      return false;
    }
    rep(i, ModsSize) {
      if (get_hash(i, a_start, a_end) != rh.get_hash(i, b_start, b_end)) {
        return false;
      }
    }
    return true;
  }
};

int fact[13];
int sizes[1 << 12];

int main() {

  fact[0] = 1;
  REP(i, 1, 13) fact[i] = fact[i - 1] * i;

  for (int N, M; cin >> N >> M && (N | M);) {
    vector<RollingHash> vs;
    set<string> se;
    rep(i, N) {
      string s;
      cin >> s;
      se.insert(s);
      vs.push_back(RollingHash(s));
    }

    rep(i, 1 << N) sizes[i] = 0;
    rep(S, 1 << N) {
      rep(i, N) {
        if (S >> i & 1)
          continue;
        sizes[S | (1 << i)] += vs[i].N;
      }
    }

    string t;
    rep(i, M) {
      char s[5001];
      cin >> s, t += s;
    }

    RollingHash T(t);
    int TSize = t.size();

    ll sum = 0;
    rep(st, TSize - sizes[(1 << N) - 1] + 1) {
      int dp[1 << N];
      memset(dp, 0, sizeof dp);
      dp[0] = 1;
      rep(S, 1 << N) {
        if (!dp[S])
          continue;
        rep(i, N) {
          if (S >> i & 1)
            continue;
          if (T.same(st + sizes[S], st + sizes[S | (1 << i)], 0, vs[i].N,
                     vs[i])) {
            dp[S | (1 << i)] += dp[S];
          }
        }
      }
      sum += dp[(1 << N) - 1];
    }
    cout << sum / (fact[vs.size()] / fact[se.size()]) << endl;
  }

  return 0;
}