Problem p01551 (C++)

Buggy submission (status: Runtime Error):


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (k); i < (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))
#define D10 fixed << setprecision(10)
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--------------------*/

int A, T, G, C, m;
int dp[51][51][51][51];
map<string, int> mp;
vector<vs> v;
vs tar;

ll solve(int i, int a, int t, int g, int c) {
  ll res = 0;
  if (i == tar.size()) {
    if (a == A && t == T && g == G && c == C)
      return 1;
    else
      return 0;
  }
  if (dp[a][t][g][c] >= 0)
    return dp[a][t][g][c];
  REP(j, tar[i].size()) {
    if (tar[i][j] == 'A')
      res += solve(i + 1, a + 1, t, g, c);
    if (tar[i][j] == 'T')
      res += solve(i + 1, a, t + 1, g, c);
    if (tar[i][j] == 'G')
      res += solve(i + 1, a, t, g + 1, c);
    if (tar[i][j] == 'C')
      res += solve(i + 1, a, t, g, c + 1);
    res %= MOD;
  }
  return dp[a][t][g][c] = res % MOD;
}

bool f;
vs search(int i) {
  vs res;
  REP(j, v[i].size()) {
    if (v[i][j][0] == '[')
      res.push_back(v[i][j].substr(1, v[i][j].size() - 2));
    else {
      int nx = mp[v[i][j]];
      vs tmp = search(nx);
      if (tmp == vs{"-1"} || res.size() + tmp.size() > A + T + G + C)
        return vs{"-1"};
      res.insert(res.end(), ALL(tmp));
    }
  }
  return res;
}

int main() {
  MS(dp, -1);
  cin >> A >> T >> G >> C >> m;
  string s;
  int tmp = -1;
  v.resize(m);
  while (cin >> s) {
    if (s.back() == ':') {
      tmp++;
      s.pop_back();
      mp[s] = tmp;
    } else {
      v[tmp].push_back(s);
    }
  }
  f = true;
  tar = search(0);
  if (!f) {
    puts("0");
    return 0;
  }
  cout << solve(0, 0, 0, 0, 0) % MOD << endl;
  return 0;
}

Fixed submission:


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (k); i < (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))
#define D10 fixed << setprecision(10)
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--------------------*/

int A, T, G, C, m;
int dp[51][51][51][51];
map<string, int> mp;
vector<vs> v;
vs tar;

ll solve(int i, int a, int t, int g, int c) {
  ll res = 0;
  if (a > A || t > T || g > G || c > C)
    return 0;
  if (i == tar.size()) {
    if (a == A && t == T && g == G && c == C)
      return 1;
    else
      return 0;
  }
  if (dp[a][t][g][c] >= 0)
    return dp[a][t][g][c];
  REP(j, tar[i].size()) {
    if (tar[i][j] == 'A')
      res += solve(i + 1, a + 1, t, g, c);
    if (tar[i][j] == 'T')
      res += solve(i + 1, a, t + 1, g, c);
    if (tar[i][j] == 'G')
      res += solve(i + 1, a, t, g + 1, c);
    if (tar[i][j] == 'C')
      res += solve(i + 1, a, t, g, c + 1);
    res %= MOD;
  }
  return dp[a][t][g][c] = res % MOD;
}

bool f;
vs search(int i) {
  vs res;
  REP(j, v[i].size()) {
    if (v[i][j][0] == '[')
      res.push_back(v[i][j].substr(1, v[i][j].size() - 2));
    else {
      int nx = mp[v[i][j]];
      vs tmp = search(nx);
      if (tmp == vs{"-1"} || res.size() + tmp.size() > A + T + G + C)
        return vs{"-1"};
      res.insert(res.end(), ALL(tmp));
    }
  }
  return res;
}

int main() {
  MS(dp, -1);
  cin >> A >> T >> G >> C >> m;
  string s;
  int tmp = -1;
  v.resize(m);
  while (cin >> s) {
    if (s.back() == ':') {
      tmp++;
      s.pop_back();
      mp[s] = tmp;
    } else {
      v[tmp].push_back(s);
    }
  }
  f = true;
  tar = search(0);
  if (!f) {
    puts("0");
    return 0;
  }
  cout << solve(0, 0, 0, 0, 0) % MOD << endl;
  return 0;
}