Problem p00870 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/
const ll mod[] = {999999937, 1000000007}, base = 10000103;

struct RollingHash {
  int n;
  vector<ll> hs[2], pw[2];
  RollingHash(){};
  RollingHash(const string &s) {
    n = s.size();
    REP(i, 2) {
      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] * base % mod[i];
        hs[i][j + 1] = (hs[i][j] * base + s[j]) % mod[i];
      }
    }
  }

  ll hash(int l, int r, int i) {
    return ((hs[i][r] - hs[i][l] * pw[i][r - l]) % mod[i] + mod[i]) % mod[i];
  }

  bool match(int l1, int r1, int l2, int r2) {
    return (hash(l1, r1, 0) == hash(l2, r2, 0)) &&
           (hash(l1, r1, 1) == hash(l2, r2, 1));
  }
};

int n, m;
int dp[1 << 12][5555];
vs v;
// vector<set<int>> match;
vector<vi> match;

int solve(int bit, int p) {
  if (bit == (1 << n) - 1)
    return 1;
  if (dp[bit][p] >= 0)
    return dp[bit][p];
  int res = 0;
  REP(i, match[p].size()) {
    if ((bit >> match[p][i]) & 1)
      continue;
    chmax(res, solve(bit | (1 << match[p][i]), p + v[match[p][i]].size()));
  }
  return dp[bit][p] = res;
}

int main() {
  cin.sync_with_stdio(false);
  cout << fixed << setprecision(10);
  while (cin >> n >> m, n) {
    MS(dp, -1);
    v.clear(), match.clear();
    v.resize(n);
    string s;
    REP(i, n) cin >> v[i];
    REP(i, m) {
      string t;
      cin >> t;
      s += t;
    }
    RollingHash hs(s);
    match.resize(s.size());
    REP(i, n) {
      RollingHash pat(v[i]);
      ll pat1 = pat.hash(0, v[i].size(), 0);
      ll pat2 = pat.hash(0, v[i].size(), 1);
      REP(j, (int)s.size() - (int)v[i].size() + 1) {
        ll hs1 = hs.hash(j, j + v[i].size(), 0);
        ll hs2 = hs.hash(j, j + v[i].size(), 1);
        if (pat1 == hs1 && pat2 == hs2)
          match[j].push_back(i);
      }
    }
    int len = 0;
    for (auto i : v)
      len += i.size();
    ll ans = 0;
    REP(i, (int)s.size() - len + 1) { ans += solve(0, i); }
    cout << ans << endl;
  }
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/
const ll mod[] = {999999937, 1000000007}, base = 10000103;

struct RollingHash {
  int n;
  vector<ll> hs[2], pw[2];
  RollingHash(){};
  RollingHash(const string &s) {
    n = s.size();
    REP(i, 2) {
      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] * base % mod[i];
        hs[i][j + 1] = (hs[i][j] * base + s[j]) % mod[i];
      }
    }
  }

  ll hash(int l, int r, int i) {
    return ((hs[i][r] - hs[i][l] * pw[i][r - l]) % mod[i] + mod[i]) % mod[i];
  }

  bool match(int l1, int r1, int l2, int r2) {
    return (hash(l1, r1, 0) == hash(l2, r2, 0)) &&
           (hash(l1, r1, 1) == hash(l2, r2, 1));
  }
};

int n, m;
short dp[1 << 12][5555];
vs v;
// vector<set<int>> match;
vector<vi> match;

int solve(int bit, int p) {
  if (bit == (1 << n) - 1)
    return 1;
  if (dp[bit][p] >= 0)
    return dp[bit][p];
  int res = 0;
  REP(i, match[p].size()) {
    if ((bit >> match[p][i]) & 1)
      continue;
    chmax(res, solve(bit | (1 << match[p][i]), p + v[match[p][i]].size()));
  }
  return dp[bit][p] = res;
}

int main() {
  cin.sync_with_stdio(false);
  cout << fixed << setprecision(10);
  while (cin >> n >> m, n) {
    MS(dp, -1);
    v.clear(), match.clear();
    v.resize(n);
    string s;
    REP(i, n) cin >> v[i];
    REP(i, m) {
      string t;
      cin >> t;
      s += t;
    }
    RollingHash hs(s);
    match.resize(s.size());
    REP(i, n) {
      RollingHash pat(v[i]);
      ll pat1 = pat.hash(0, v[i].size(), 0);
      ll pat2 = pat.hash(0, v[i].size(), 1);
      REP(j, (int)s.size() - (int)v[i].size() + 1) {
        ll hs1 = hs.hash(j, j + v[i].size(), 0);
        ll hs2 = hs.hash(j, j + v[i].size(), 1);
        if (pat1 == hs1 && pat2 == hs2)
          match[j].push_back(i);
      }
    }
    int len = 0;
    for (auto i : v)
      len += i.size();
    ll ans = 0;
    REP(i, (int)s.size() - len + 1) { ans += solve(0, i); }
    cout << ans << endl;
  }
  return 0;
}