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

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for (int(i) = 0; (i) < (int)(n); ++(i))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout << #x " = " << ((x)) << endl
template <class T, class U>
ostream &operator<<(ostream &o, const pair<T, U> &p) {
  o << "(" << p.fi << "," << p.se << ")";
  return o;
}
template <class T> ostream &operator<<(ostream &o, const vector<T> &v) {
  o << "[";
  for (T t : v) {
    o << t << ",";
  }
  o << "]";
  return o;
}

const int N = 12, TT = 5000;
bool dp[1 << N];
int len[1 << N];
bool match[N][TT];

int main() {
  int n, m;
  while (cin >> n >> m, n) {
    vector<string> s(n);
    rep(i, n) cin >> s[i];

    string t = "";
    while (m--) {
      string tmp;
      cin >> tmp;
      t += tmp;
    }

    vector<int> sz(n);
    int S = 0;
    rep(i, n) {
      sz[i] = s[i].size();
      S += sz[i];
    }
    int T = t.size();
    // S <= 240, T <= 5000

    rep(mask, 1 << n) {
      len[mask] = 0;
      rep(i, n) if (mask >> i & 1) len[mask] += sz[i];
    }

    fill(match[0], match[N], false);
    rep(i, n) {
      rep(j, T - sz[i] + 1) { match[i][j] = (s[i] == t.substr(j, sz[i])); }
    }

    int ans = 0;
    rep(i, T - S + 1) {
      fill(dp, dp + (1 << N), false);
      dp[0] = true;
      rep(mask, 1 << n) if (dp[mask]) {
        rep(j, n) if (!(mask >> j & 1)) {
          int nx = mask | (1 << j);
          if (match[j][i + len[mask]])
            dp[nx] = true;
        }
      }

      if (dp[(1 << n) - 1])
        ++ans;
    }
    cout << ans << endl;
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for (int(i) = 0; (i) < (int)(n); ++(i))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout << #x " = " << ((x)) << endl
template <class T, class U>
ostream &operator<<(ostream &o, const pair<T, U> &p) {
  o << "(" << p.fi << "," << p.se << ")";
  return o;
}
template <class T> ostream &operator<<(ostream &o, const vector<T> &v) {
  o << "[";
  for (T t : v) {
    o << t << ",";
  }
  o << "]";
  return o;
}

struct RollingHash {
  static const int MD = 2;
  static const vector<ll> hash_base, hash_mod;

  int n;
  vector<ll> hs[MD], pw[MD];

  RollingHash() {}
  RollingHash(const string &s) {
    n = s.size();
    rep(i, MD) {
      hs[i].assign(n + 1, 0);
      pw[i].assign(n + 1, 0);
      hs[i][0] = 0;
      pw[i][0] = 1;
      rep(j, n) {
        pw[i][j + 1] = pw[i][j] * hash_base[i] % hash_mod[i];
        hs[i][j + 1] = (hs[i][j] * hash_base[i] + s[j]) % hash_mod[i];
      }
    }
  }

  // 1-index
  ll hash_value(int l, int r, int i) {
    return ((hs[i][r] - hs[i][l] * pw[i][r - l]) % hash_mod[i] + hash_mod[i]) %
           hash_mod[i];
  }

  bool match(int l1, int r1, int l2, int r2) {
    bool ret = true;
    rep(i, MD) ret &= (hash_value(l1 - 1, r1, i) == hash_value(l2 - 1, r2, i));
    return ret;
  }

  vector<ll> calc(int l, int r) {
    vector<ll> ret(MD);
    rep(i, MD) ret[i] = hash_value(l - 1, r, i);
    return ret;
  }
};
const vector<ll> RollingHash::hash_base{1009, 1021, 1013};
const vector<ll> RollingHash::hash_mod{1000000009, 1000000007, 1000000021};

const int N = 1 << 12;
bool dp[N];
int len[N];

int main() {
  int n, m;
  while (cin >> n >> m, n) {
    vector<string> s(n);
    rep(i, n) cin >> s[i];

    string t = "";
    while (m--) {
      string tmp;
      cin >> tmp;
      t += tmp;
    }

    vector<int> sz(n);
    int S = 0;
    rep(i, n) {
      sz[i] = s[i].size();
      S += sz[i];
    }
    int T = t.size();
    // S <= 240, T <= 5000

    vector<RollingHash> hs(n);
    rep(i, n) hs[i] = RollingHash(s[i]);
    RollingHash ht(t);

    rep(mask, 1 << n) {
      len[mask] = 0;
      rep(i, n) if (mask >> i & 1) len[mask] += s[i].size();
    }

    int ans = 0;
    rep(i, T - S + 1) {
      fill(dp, dp + N, false);
      dp[0] = true;
      rep(mask, 1 << n) if (dp[mask]) {
        rep(j, n) if (!(mask >> j & 1)) {
          int nx = mask | (1 << j);

          bool flg = true;
          rep(k, 2) {
            flg &= (hs[j].hash_value(1, sz[j], k) ==
                    ht.hash_value(1 + i + len[mask], 1 + i + len[nx] - 1, k));
          }

          dp[nx] |= flg;
        }
      }

      if (dp[(1 << n) - 1])
        ++ans;
    }
    cout << ans << endl;
  }
  return 0;
}