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

#include <bits/stdc++.h>
using namespace std;

const int MOD = 1e9 + 7;

const string table = "ATGC";
typedef vector<string> Term;

int Na, Nt, Ng, Nc;
int M;

string flabel;
map<string, vector<string>> terms;
vector<int> symbols;
int memo[55][55][55][55];

int dfs(int a, int t, int g, int c) {
  if (memo[a][t][g][c] >= 0)
    return memo[a][t][g][c];

  if (a > Na || t > Nt || g > Ng || c > Nc)
    return memo[a][t][g][c] = 0;
  if (a == Na && t == Nt && g == Ng && c == Nc)
    return 1;

  int l = a + t + g + c;
  int res = 0;
  if (symbols[l] & 1)
    res = (res + dfs(a + 1, t, g, c)) % MOD;
  if (symbols[l] & 2)
    res = (res + dfs(a, t + 1, g, c)) % MOD;
  if (symbols[l] & 4)
    res = (res + dfs(a, t, g + 1, c)) % MOD;
  if (symbols[l] & 8)
    res = (res + dfs(a, t, g, c + 1)) % MOD;
  return memo[a][t][g][c] = res;
}

bool dfs(string label) {
  auto term = terms[label];

  for (auto t : term) {
    if (t[0] == '[') {
      int sym = 0;
      for (int i = 1; i < t.size() - 1; i++) {
        sym |= 1 << table.find(t[i]);
      }
      symbols.push_back(sym);
      if (symbols.size() > Na + Nt + Ng + Nc)
        return false;
    } else {
      if (!dfs(t))
        return false;
    }
  }
  return true;
}

int solve() {
  memset(memo, -1, sizeof(memo));

  if (!dfs(flabel))
    return 0;

  return dfs(0, 0, 0, 0);
}

int main() {
  cin >> Na >> Nt >> Ng >> Nc;
  cin >> M;
  cin.ignore();

  for (int i = 0; i < M; i++) {
    string s;
    getline(cin, s);
    stringstream ss(s);
    string label;
    ss >> label;
    label = label.substr(0, label.size() - 1);

    if (i == 0)
      flabel = label;

    string t;
    while (ss >> t)
      terms[label].push_back(t);
  }
  cout << solve() << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll MOD = 1e9 + 7;

struct Term {
  vector<int> symbols;
  vector<string> labels;

  //    Term(string label): label(label){};
};

int to_int(string s) {
  int res = 0;
  string table = "ATGC";
  for (int i = 1; i < s.size() - 1; i++) {
    char c = s[i];
    res |= 1 << table.find(c);
  }
  return res;
};

int Na, Nt, Ng, Nc;
int M;

string flabel;
map<string, Term> terms;

bool dfs(string label, vector<int> &symbols) {
  auto term = terms[label];

  for (int i = 0; i < term.symbols.size(); i++) {
    int s = term.symbols[i];
    if (0 <= s) {
      symbols.push_back(s);
    } else {
      string l = term.labels[i];
      dfs(l, symbols);
      if (symbols.size() > Na + Nt + Ng + Nc)
        return false;
    }
  }
  return true;
}

int solve() {
  vector<int> symbols;
  if (!dfs(flabel, symbols))
    return 0;

  map<vector<int>, ll> count;
  count[{0, 0, 0, 0}] = 1;

  for (auto v : symbols) {
    map<vector<int>, ll> tcount;
    for (auto p : count) {
      for (int i = 0; i < 4; i++)
        if ((v >> i) & 1) {
          vector<int> vec = p.first;
          vec[i]++;
          tcount[vec] = (tcount[vec] + p.second) % MOD;
        }
    }
    count = tcount;
  }
  // cout << count.size() << endl;
  return count[{Na, Nt, Ng, Nc}];
}

int main() {
  cin >> Na >> Nt >> Ng >> Nc;
  cin >> M;
  cin.ignore();

  for (int i = 0; i < M; i++) {
    string s;
    getline(cin, s);
    stringstream ss(s);
    string label;
    ss >> label;
    label = label.substr(0, label.size() - 1);

    if (i == 0)
      flabel = label;

    //        Term term(label);
    Term term;

    string t;
    while (ss >> t) {
      if (t[0] == '[') {
        term.symbols.push_back(to_int(t));
        term.labels.push_back("");
      } else {
        term.symbols.push_back(-1);
        term.labels.push_back(t);
      }
    }
    terms[label] = term;
  }

  cout << solve() << endl;

  return 0;
}