Problem p01551 (C++) — buggy submission, verdict: Runtime Error

#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;

vector<string> split(string s, const string &t) {
  vector<string> v;
  for (int p = 0; (p = s.find(t)) != s.npos;) {
    v.push_back(s.substr(0, p));
    s = s.substr(p + t.size());
  }
  v.push_back(s);
  return v;
}

typedef long long ll;
const int MAX_LEN = 201;
const ll mod = 1000000007ll;
ll dp[52][52][52][52];
int Na, Nt, Ng, Nc;
int m;

map<string, vector<string>> rules;

void update(const char symbol, const int sum) {
  for (int a = 0; a <= sum && a <= Na; ++a) {
    for (int t = 0; a + t <= sum && t <= Nt; ++t) {
      for (int g = 0; a + t + g <= sum && g <= Ng; ++g) {
        int c = sum - a - t - g;
        if (c > Nc)
          continue;
        switch (symbol) {
        case 'A':
          dp[a + 1][t][g][c] += dp[a][t][g][c];
          dp[a + 1][t][g][c] %= mod;
          break;
        case 'T':
          dp[a][t + 1][g][c] += dp[a][t][g][c];
          dp[a][t + 1][g][c] %= mod;
          break;
        case 'G':
          dp[a][t][g + 1][c] += dp[a][t][g][c];
          dp[a][t][g + 1][c] %= mod;
          break;
        case 'C':
          dp[a][t][g][c + 1] += dp[a][t][g][c];
          dp[a][t][g][c + 1] %= mod;
          break;
        }
      }
    }
  }
}

vector<string> terminals;

void dfs(const string &rule) {
  const vector<string> &children = rules[rule];
  for (vector<string>::const_iterator it = children.begin();
       it != children.end(); ++it) {
    const string &term = *it;
    if (terminals.size() > Na + Nt + Nc + Ng)
      break;
    if (term[0] == '[') {
      // terminal
      terminals.push_back(term);
      if (terminals.size() > Na + Nt + Nc + Ng)
        break;
    } else {
      dfs(term);
    }
  }
}

int main() {
  cin >> Na >> Nt >> Ng >> Nc;
  cin >> m;
  cin.ignore();
  terminals.clear();

  string firstRule = "";
  string line;
  for (int i = 0; i < m; ++i) {
    getline(cin, line);
    vector<string> vs = split(line, " ");
    vector<string> children;
    for (int j = 1; j < vs.size(); ++j)
      children.push_back(vs[j]);
    rules[vs[0].substr(0, vs[0].length() - 1)] = children;
    if (firstRule == "")
      firstRule = vs[0].substr(0, vs[0].length() - 1);
  }

  memset(dp, 0, sizeof(dp));
  dp[0][0][0][0] = 1;
  dfs(firstRule);
  if (terminals.size() != Na + Nt + Nc + Ng) {
    cout << 0 << endl;
    return 0;
  }

  for (int i = 0; i < terminals.size(); ++i) {
    const string &term = terminals[i];
    for (int j = 1; j < term.length() - 1; ++j)
      update(term[j], i);
  }
  cout << dp[Na][Nt][Ng][Nc] << endl;
}

Error: 0

Fixed submission:

#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;

vector<string> split(string s, const string &t) {
  vector<string> v;
  for (int p = 0; (p = s.find(t)) != s.npos;) {
    v.push_back(s.substr(0, p));
    s = s.substr(p + t.size());
  }
  v.push_back(s);
  return v;
}

typedef long long ll;
const int MAX_LEN = 201;
const ll mod = 1000000007ll;
ll dp[51][51][51][51];
int Na, Nt, Ng, Nc;
int m;

map<string, vector<string>> rules;

void update(const char symbol, const int sum) {
  for (int a = 0; a <= sum && a <= Na; ++a) {
    for (int t = 0; a + t <= sum && t <= Nt; ++t) {
      for (int g = 0; a + t + g <= sum && g <= Ng; ++g) {
        int c = sum - a - t - g;
        if (c > Nc)
          continue;
        switch (symbol) {
        case 'A':
          dp[a + 1][t][g][c] += dp[a][t][g][c];
          dp[a + 1][t][g][c] %= mod;
          break;
        case 'T':
          dp[a][t + 1][g][c] += dp[a][t][g][c];
          dp[a][t + 1][g][c] %= mod;
          break;
        case 'G':
          dp[a][t][g + 1][c] += dp[a][t][g][c];
          dp[a][t][g + 1][c] %= mod;
          break;
        case 'C':
          dp[a][t][g][c + 1] += dp[a][t][g][c];
          dp[a][t][g][c + 1] %= mod;
          break;
        }
      }
    }
  }
}

vector<string> terminals;

void dfs(const string &rule) {
  const vector<string> &children = rules[rule];
  for (vector<string>::const_iterator it = children.begin();
       it != children.end(); ++it) {
    const string &term = *it;
    if (terminals.size() > Na + Nt + Nc + Ng)
      break;
    if (term[0] == '[') {
      // terminal
      terminals.push_back(term);
    } else {
      dfs(term);
    }
  }
}

int main() {
  cin >> Na >> Nt >> Ng >> Nc;
  cin >> m;
  cin.ignore();
  terminals.clear();

  string firstRule = "";
  string line;
  for (int i = 0; i < m; ++i) {
    getline(cin, line);
    vector<string> vs = split(line, " ");
    vector<string> children;
    for (int j = 1; j < vs.size(); ++j)
      children.push_back(vs[j]);
    rules[vs[0].substr(0, vs[0].length() - 1)] = children;
    if (firstRule == "")
      firstRule = vs[0].substr(0, vs[0].length() - 1);
  }

  memset(dp, 0, sizeof(dp));
  dp[0][0][0][0] = 1;
  dfs(firstRule);
  if (terminals.size() != Na + Nt + Nc + Ng) {
    cout << 0 << endl;
    return 0;
  }

  for (int i = 0; i < terminals.size(); ++i) {
    const string &term = terminals[i];
    for (int j = 1; j < term.length() - 1; ++j)
      update(term[j], i);
  }
  cout << dp[Na][Nt][Ng][Nc] << endl;
}