Problem p01551 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define REP(i, m, n) for (int i = (int)(m); i < (int)(n); ++i)
#define rep(i, n) REP(i, 0, n)
using ll = long long;
const int inf = 1e9 + 7;
const ll longinf = 1LL << 60;
const ll mod = 1e9 + 7;

string dp[55];
string s[55];
map<string, int> mp;

bool ischar(char c) {
  if ('a' <= c && c <= 'z')
    return true;
  if ('A' <= c && c <= 'Z')
    return true;
  if (c == '[' || c == ']' || c == ':' || c == '*')
    return true;
  return false;
}
string rec(int idx) {
  if (dp[idx] != "")
    return dp[idx];
  string ret = "";
  int i = 1;
  while (ischar(s[idx][i]))
    ++i;
  while (1) {
    ++i;
    if (s[idx][i] == '*')
      break;
    if (s[idx][i] == '[') {
      char cur = 0;
      while (ischar(s[idx][i])) {
        if (s[idx][i] == 'A')
          cur += 8;
        if (s[idx][i] == 'T')
          cur += 4;
        if (s[idx][i] == 'G')
          cur += 2;
        if (s[idx][i] == 'C')
          cur += 1;
        ++i;
      }
      ret += cur;
    } else {
      string nxt = "";
      while (ischar(s[idx][i])) {
        nxt += s[idx][i];
        ++i;
      }
      ret += rec(mp[nxt]);
    }
    if (ret.size() > 300) {
      ret.resize(300);
      return dp[idx] = ret;
    }
  }
  return dp[idx] = ret;
}

ll dpp[55][55][55][55];
int main() {
  int a, g, c, t;
  cin >> a >> g >> c >> t;
  int n;
  scanf("%d ", &n);
  rep(i, n) { getline(cin, s[i]); }
  rep(i, n) {
    s[i] += " *";
    string na = "";
    int j = 0;
    while (s[i][j] != ':') {
      na += s[i][j++];
    }
    mp[na] = i;
  }
  string res = rec(0);
  if (res.size() != a + g + c + t) {
    cout << 0 << endl;
    return 0;
  }
  dpp[0][0][0][0] = 1;
  n = res.size();
  rep(i, 55) rep(j, 55) rep(k, 55) rep(l, 55) {
    dpp[i][j][k][l] %= mod;
    if (i + j + k + l >= n)
      break;
    int cur = i + j + k + l;
    cur = res[cur];
    if (cur & 8)
      dpp[i + 1][j][k][l] += dpp[i][j][k][l];
    if (cur & 4)
      dpp[i][j + 1][k][l] += dpp[i][j][k][l];
    if (cur & 2)
      dpp[i][j][k + 1][l] += dpp[i][j][k][l];
    if (cur & 1)
      dpp[i][j][k][l + 1] += dpp[i][j][k][l];
  }
  cout << dpp[a][g][c][t] << endl;
  return 0;
}


Fixed submission:
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define REP(i, m, n) for (int i = (int)(m); i < (int)(n); ++i)
#define rep(i, n) REP(i, 0, n)
using ll = long long;
const int inf = 1e9 + 7;
const ll longinf = 1LL << 60;
const ll mod = 1e9 + 7;

string dp[55];
string s[55];
map<string, int> mp;

bool ischar(char c) {
  if ('a' <= c && c <= 'z')
    return true;
  if ('A' <= c && c <= 'Z')
    return true;
  if (c == '[' || c == ']' || c == ':' || c == '*')
    return true;
  return false;
}
string rec(int idx) {
  if (dp[idx] != "")
    return dp[idx];
  string ret = "";
  int i = 1;
  while (ischar(s[idx][i]))
    ++i;
  while (1) {
    ++i;
    if (s[idx][i] == '*')
      break;
    if (s[idx][i] == '[') {
      char cur = 0;
      while (ischar(s[idx][i])) {
        if (s[idx][i] == 'A')
          cur += 8;
        if (s[idx][i] == 'T')
          cur += 4;
        if (s[idx][i] == 'G')
          cur += 2;
        if (s[idx][i] == 'C')
          cur += 1;
        ++i;
      }
      ret += cur;
    } else {
      string nxt = "";
      while (ischar(s[idx][i])) {
        nxt += s[idx][i];
        ++i;
      }
      ret += rec(mp[nxt]);
    }
    if (ret.size() > 300) {
      ret.resize(300);
      return dp[idx] = ret;
    }
  }
  return dp[idx] = ret;
}

ll dpp[55][55][55][55];
int main() {
  int a, g, c, t;
  cin >> a >> g >> c >> t;
  int n;
  scanf("%d ", &n);
  rep(i, n) { getline(cin, s[i]); }
  rep(i, n) {
    s[i] += " *";
    string na = "";
    int j = 0;
    while (s[i][j] != ':') {
      na += s[i][j++];
    }
    mp[na] = i;
  }
  string res = rec(0);
  if (res.size() != a + g + c + t) {
    cout << 0 << endl;
    return 0;
  }
  dpp[0][0][0][0] = 1;
  n = res.size();
  rep(i, 51) rep(j, 51) rep(k, 51) rep(l, 51) {
    dpp[i][j][k][l] %= mod;
    if (i + j + k + l >= n)
      break;
    int cur = i + j + k + l;
    cur = res[cur];
    if (cur & 8)
      dpp[i + 1][j][k][l] += dpp[i][j][k][l];
    if (cur & 4)
      dpp[i][j + 1][k][l] += dpp[i][j][k][l];
    if (cur & 2)
      dpp[i][j][k + 1][l] += dpp[i][j][k][l];
    if (cur & 1)
      dpp[i][j][k][l + 1] += dpp[i][j][k][l];
  }
  cout << dpp[a][g][c][t] << endl;
  return 0;
}