Problem p01551 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int, int> pii;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;

vector<string> v;
vector<string> vec[51];
map<string, int> mp;

int NUM;
void rec(int now) {
  FOR(it, vec[now]) {
    string s = *it;
    if (s[0] == '[') {
      v.push_back(s.substr(1, s.size() - 2));
      if (v.size() > NUM)
        throw 0;
    } else {
      rec(mp[s]);
    }
  }
}

ll dp[52][52][52][52];

int main() {
  int Na, Nt, Ng, Nc;
  while (cin >> Na >> Nt >> Ng >> Nc) {
    NUM = Na + Nt + Ng + Nc;
    int m;
    cin >> m;
    string line;
    getline(cin, line);
    REP(i, m) vec[i].clear();
    mp.clear();
    REP(i, m) {
      getline(cin, line);
      stringstream ss(line);
      string name;
      ss >> name;
      name = name.substr(0, name.size() - 1);
      mp[name] = i;
      string s;
      while (ss >> s) {
        vec[i].push_back(s);
      }
    }
    v.clear();
    try {
      rec(0);
    } catch (int a) {
      cout << 0 << endl;
      continue;
    }

    // FOR(it, v) {
    //   cout << *it << " ";
    // }
    // cout << endl;
    if (v.size() != Na + Nt + Ng + Nc) {
      puts("0");
      continue;
    }

    const int mod = 1e9 + 7;
    memset(dp, 0, sizeof(dp));
    dp[0][0][0][0] = 1;
    REP(i, Na + 1) {
      REP(j, Nt + 1) {
        REP(k, Ng + 1) {
          REP(l, Nc + 1) {
            int now = i + j + k + l;
            if (now >= v.size())
              continue;
            FOR(it, v[now]) {
              int ii = i + (*it == 'A');
              int jj = j + (*it == 'T');
              int kk = k + (*it == 'G');
              int ll = l + (*it == 'C');
              (dp[ii][jj][kk][ll] += dp[i][j][k][l]) %= mod;
            }
          }
        }
      }
    }
    cout << dp[Na][Nt][Ng][Nc] << endl;
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int, int> pii;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;

vector<string> v;
map<string, vector<string>> mp;

void rec(string now) {
  FOR(it, mp[now]) {
    string &s = *it;
    if (s[0] == '[') {
      v.push_back(s.substr(1, s.size() - 2));
    } else {
      rec(s);
    }
  }
}

int dp[2][52][52][52];

int main() {
  int Na, Nt, Ng, Nc;
  while (cin >> Na >> Nt >> Ng >> Nc) {
    int m;
    cin >> m;
    string line;
    getline(cin, line);
    mp.clear();
    string start;
    REP(i, m) {
      getline(cin, line);
      stringstream ss(line);
      string name;
      ss >> name;
      name = name.substr(0, name.size() - 1);
      if (i == 0)
        start = name;
      string s;
      while (ss >> s) {
        mp[name].push_back(s);
      }
    }
    v.clear();
    rec(start);

    // FOR(it, v) {
    //   cout << *it << " ";
    // }
    // cout << endl;
    if (v.size() != Na + Nt + Ng + Nc) {
      puts("0");
      continue;
    }

    const int mod = 1e9 + 7;
    memset(dp, 0, sizeof(dp));
    dp[0][0][0][0] = 1;
    REP(i, Na + 1) {
      REP(j, Nt + 1) REP(k, Ng + 1) REP(l, Nc + 1) dp[(i + 1) % 2][j][k][l] = 0;
      REP(j, Nt + 1) {
        REP(k, Ng + 1) {
          REP(l, Nc + 1) {
            int now = i + j + k + l;
            if (now >= v.size())
              continue;
            FOR(it, v[now]) {
              int ii = i + (*it == 'A');
              int jj = j + (*it == 'T');
              int kk = k + (*it == 'G');
              int ll = l + (*it == 'C');
              (dp[ii % 2][jj][kk][ll] += dp[i % 2][j][k][l]) %= mod;
            }
          }
        }
      }
    }
    cout << dp[Na][Nt][Ng][Nc] << endl;
  }
}