Problem p01551 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <iostream>
#include <string>
#include <vector>
using namespace std;

#define MAX_N 100
#define MOD 1000000007

int A, B, C, D, N;
int dp1[MAX_N];
string S, U[MAX_N];
vector<string> T[MAX_N];
vector<string> W[MAX_N];
int X[200][4];
char DNA[5] = "ATGC";
int dp[300][70][70][70];

int solve() {
  for (int i = N - 1; i >= 0; i--) {
    for (int j = 0; j < T[i].size(); j++) {
      if (T[i][j][0] - 'A' >= 26) {
        for (int k = 0; k < N; k++) {
          if (T[i][j] == U[k]) {
            for (int l = 0; l < W[k].size(); l++) {
              W[i].push_back(W[k][l]);
            }
          }
        }
      } else {
        W[i].push_back(T[i][j]);
      }
    }
  }
  for (int i = 0; i < W[0].size(); i++) {
    for (int j = 0; j < W[0][i].size(); j++) {
      for (int k = 0; k < 4; k++) {
        if (DNA[k] == W[0][i][j]) {
          X[i][k] = 1;
        }
      }
    }
  }
  dp[0][0][0][0] = 1;
  for (int i = 0; i < W[0].size(); i++) {
    for (int j = 0; j <= A; j++) {
      for (int k = 0; k <= B; k++) {
        for (int l = 0; l <= C; l++) {
          if (X[i][0] == 1) {
            dp[i + 1][j + 1][k][l] += dp[i][j][k][l];
            dp[i + 1][j + 1][k][l] %= MOD;
          }
          if (X[i][1] == 1) {
            dp[i + 1][j][k + 1][l] += dp[i][j][k][l];
            dp[i + 1][j][k + 1][l] %= MOD;
          }
          if (X[i][2] == 1) {
            dp[i + 1][j][k][l + 1] += dp[i][j][k][l];
            dp[i + 1][j][k][l + 1] %= MOD;
          }
          if (X[i][3] == 1) {
            dp[i + 1][j][k][l] += dp[i][j][k][l];
            dp[i + 1][j][k][l] %= MOD;
          }
        }
      }
    }
  }
  return dp[W[0].size()][A][B][C];
}

int main() {
  cin >> A >> B >> C >> D >> N;
  for (int i = 0; i < N; i++) {
    S = "";
    while (S == "") {
      getline(cin, S);
    }
    S += ' ';
    string V = "";
    for (int j = 0; j < S.size(); j++) {
      if (S[j] == ':') {
        U[i] = V;
        V = "";
        j++;
      } else if (S[j] == ']' || S[j] == ' ') {
        if (S[j - 1] != ']') {
          T[i].push_back(V);
          V = "";
        }
      } else if (S[j] != '[') {
        V += S[j];
      }
    }
  }
  for (int i = N - 1; i >= 0; i--) {
    int score = 0;
    for (int j = 0; j < T[i].size(); j++) {
      if (T[i][j][0] - 'A' >= 26) {
        for (int k = 0; k < N; k++) {
          if (T[i][j] == U[k]) {
            score += dp1[k];
          }
        }
      } else {
        score += 1;
      }
    }
    if (score >= 2000) {
      dp1[0] = 2000;
      break;
    }
    dp1[i] = score;
  }
  if (dp1[0] != A + B + C + D) {
    cout << "0" << endl;
    goto E;
  }
  cout << solve() << endl;
E:;
  return 0;
}

Fixed submission:
#include <iostream>
#include <string>
#include <vector>
using namespace std;

#define MAX_N 100
#define MOD 1000000007

int A, B, C, D, N;
int dp1[MAX_N];
string S, U[MAX_N];
vector<string> T[MAX_N];
vector<string> W[MAX_N];
int X[200][4];
char DNA[5] = "ATGC";
int dp[216][54][54][54];

int solve() {
  for (int i = N - 1; i >= 0; i--) {
    for (int j = 0; j < T[i].size(); j++) {
      if (T[i][j][0] - 'A' >= 26) {
        for (int k = 0; k < N; k++) {
          if (T[i][j] == U[k]) {
            for (int l = 0; l < W[k].size(); l++) {
              W[i].push_back(W[k][l]);
            }
          }
        }
      } else {
        W[i].push_back(T[i][j]);
      }
    }
  }
  for (int i = 0; i < W[0].size(); i++) {
    for (int j = 0; j < W[0][i].size(); j++) {
      for (int k = 0; k < 4; k++) {
        if (DNA[k] == W[0][i][j]) {
          X[i][k] = 1;
        }
      }
    }
  }
  dp[0][0][0][0] = 1;
  for (int i = 0; i < W[0].size(); i++) {
    for (int j = 0; j <= A; j++) {
      for (int k = 0; k <= B; k++) {
        for (int l = 0; l <= C; l++) {
          if (X[i][0] == 1) {
            dp[i + 1][j + 1][k][l] += dp[i][j][k][l];
            dp[i + 1][j + 1][k][l] %= MOD;
          }
          if (X[i][1] == 1) {
            dp[i + 1][j][k + 1][l] += dp[i][j][k][l];
            dp[i + 1][j][k + 1][l] %= MOD;
          }
          if (X[i][2] == 1) {
            dp[i + 1][j][k][l + 1] += dp[i][j][k][l];
            dp[i + 1][j][k][l + 1] %= MOD;
          }
          if (X[i][3] == 1) {
            dp[i + 1][j][k][l] += dp[i][j][k][l];
            dp[i + 1][j][k][l] %= MOD;
          }
        }
      }
    }
  }
  return dp[W[0].size()][A][B][C];
}

int main() {
  cin >> A >> B >> C >> D >> N;
  for (int i = 0; i < N; i++) {
    S = "";
    while (S == "") {
      getline(cin, S);
    }
    S += ' ';
    string V = "";
    for (int j = 0; j < S.size(); j++) {
      if (S[j] == ':') {
        U[i] = V;
        V = "";
        j++;
      } else if (S[j] == ']' || S[j] == ' ') {
        if (S[j - 1] != ']') {
          T[i].push_back(V);
          V = "";
        }
      } else if (S[j] != '[') {
        V += S[j];
      }
    }
  }
  for (int i = N - 1; i >= 0; i--) {
    int score = 0;
    for (int j = 0; j < T[i].size(); j++) {
      if (T[i][j][0] - 'A' >= 26) {
        for (int k = 0; k < N; k++) {
          if (T[i][j] == U[k]) {
            score += dp1[k];
          }
        }
      } else {
        score += 1;
      }
    }
    if (score >= 2000) {
      dp1[0] = 2000;
      break;
    }
    dp1[i] = score;
  }
  if (dp1[0] != A + B + C + D) {
    cout << "0" << endl;
    goto E;
  }
  cout << solve() << endl;
E:;
  return 0;
}