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

#include <bits/stdc++.h>
#define REP(i, a, n) for (ll i = ((ll)a); i < ((ll)n); i++)
using namespace std;
typedef long long ll;

#define MOD 1000000007LL
ll dp[2][51][51][51][51];

vector<string> split(string s, string p) {
  vector<string> ret;
  ll h = 0;
  REP(i, 0, s.size() - p.size() + 1) if (s.substr(i, p.size()) == p) {
    ret.push_back(s.substr(h, i - h));
    h = i + p.size();
    i += (ll)p.size() - 1;
  }
  ret.push_back(s.substr(h, (ll)s.size() - h));
  return ret;
}

int main(void) {
  ll A, T, C, G, M;
  scanf("%lld %lld %lld %lld\\n", &A, &T, &G, &C);
  scanf("%lld\\n", &M);
  vector<string> S(M);
  REP(i, 0, M) getline(cin, S[i]);

  map<string, map<string, ll>> mp;

  for (ll m = M - 1; m >= 0; m--) {
    string name = split(S[m], ": ")[0];
    string body = split(S[m], ": ")[1];
    vector<string> items = split(body, " ");
    for (string s : items) {
      if (s[0] == '[') {
        string t = s.substr(1, s.length() - 2);
        sort(t.begin(), t.end());
        if (++mp[name][t] > A + T + C + G) {
          cout << 0 << endl;
          return 0;
        }
      } else {
        for (auto p : mp[s]) {
          string t = p.first;
          ll d = p.second;
          if ((mp[name][t] += d) > A + T + C + G) {
            cout << 0 << endl;
            return 0;
          }
        }
      }
    }
  }

  ll cur = 0, nxt = 1;
  REP(a, 0, A + 1)
  REP(t, 0, T + 1) REP(c, 0, C + 1) REP(g, 0, G + 1) dp[cur][a][t][c][g] = 0;
  dp[cur][0][0][0][0] = 1;

  string name = split(S[0], ": ")[0];
  ll cnt = 0;
  for (auto p : mp[name])
    cnt += p.second;
  if (cnt > A + T + C + G) {
    cout << 0 << endl;
    return 0;
  }
  ll q = 0;
  for (auto p : mp[name]) {
    string s = p.first;
    ll x = p.second;
    for (ll k = 0; k < x; k++) {
      REP(a, 0, A + 1)
      REP(t, 0, T + 1) REP(c, 0, C + 1) REP(g, 0, G + 1) dp[nxt][a][t][c][g] =
          0;
      REP(a, 0, A + 1) REP(t, 0, T + 1) REP(c, 0, C + 1) {
        ll g = q - a - t - c;
        if (0 <= g && g <= G)
          for (char ch : s) {
            if (ch == 'A' && a + 1 <= A)
              (dp[nxt][a + 1][t][c][g] += dp[cur][a][t][c][g]) %= MOD;
            if (ch == 'T' && t + 1 <= T)
              (dp[nxt][a][t + 1][c][g] += dp[cur][a][t][c][g]) %= MOD;
            if (ch == 'C' && c + 1 <= C)
              (dp[nxt][a][t][c + 1][g] += dp[cur][a][t][c][g]) %= MOD;
            if (ch == 'G' && g + 1 <= G)
              (dp[nxt][a][t][c][g + 1] += dp[cur][a][t][c][g]) %= MOD;
          }
      }
      swap(cur, nxt);
      q++;
    }
  }
  cout << dp[cur][A][T][C][G] << endl;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define REP(i, a, n) for (ll i = ((ll)a); i < ((ll)n); i++)
using namespace std;
typedef long long ll;

const ll MOD = 1000000007;
ll dp[2][51][51][51][51];

vector<string> split(string s, string p) {
  vector<string> ret;
  ll h = 0;
  REP(i, 0, s.size() - p.size() + 1) if (s.substr(i, p.size()) == p) {
    ret.push_back(s.substr(h, i - h));
    h = i + p.size();
    i += (ll)p.size() - 1;
  }
  ret.push_back(s.substr(h, (ll)s.size() - h));
  return ret;
}

int main(void) {
  ll A, T, C, G, M;
  scanf("%lld %lld %lld %lld\\n", &A, &T, &G, &C);
  scanf("%lld\\n", &M);
  vector<string> S(M);
  REP(i, 0, M) getline(cin, S[i]);

  map<string, map<string, ll>> mp;

  for (ll m = M - 1; m >= 0; m--) {
    string name = split(S[m], ": ")[0];
    string body = split(S[m], ": ")[1];
    vector<string> items = split(body, " ");
    for (string s : items) {
      if (s[0] == '[') {
        string t = s.substr(1, s.length() - 2);
        sort(t.begin(), t.end());
        if (++mp[name][t] > A + T + C + G) {
          cout << 0 << endl;
          return 0;
        }
      } else {
        for (auto p : mp[s]) {
          string t = p.first;
          ll d = p.second;
          if ((mp[name][t] += d) > A + T + C + G) {
            cout << 0 << endl;
            return 0;
          }
        }
      }
    }
  }

  ll cur = 0, nxt = 1;
  REP(a, 0, A + 1)
  REP(t, 0, T + 1) REP(c, 0, C + 1) REP(g, 0, G + 1) dp[cur][a][t][c][g] = 0;
  dp[cur][0][0][0][0] = 1;

  string name = split(S[0], ": ")[0];
  ll cnt = 0;
  for (auto p : mp[name])
    cnt += p.second;
  if (cnt > A + T + C + G) {
    cout << 0 << endl;
    return 0;
  }
  for (auto p : mp[name]) {
    string s = p.first;
    ll x = p.second;
    for (ll k = 0; k < x; k++) {
      REP(a, 0, A + 1)
      REP(t, 0, T + 1) REP(c, 0, C + 1) REP(g, 0, G + 1) dp[nxt][a][t][c][g] =
          0;
      REP(a, 0, A + 1)
      REP(t, 0, T + 1) REP(c, 0, C + 1)
          REP(g, 0, G + 1) if (dp[cur][a][t][c][g] > 0) for (char ch : s) {
        if (ch == 'A' && a + 1 <= A)
          (dp[nxt][a + 1][t][c][g] += dp[cur][a][t][c][g]) %= MOD;
        if (ch == 'T' && t + 1 <= T)
          (dp[nxt][a][t + 1][c][g] += dp[cur][a][t][c][g]) %= MOD;
        if (ch == 'C' && c + 1 <= C)
          (dp[nxt][a][t][c + 1][g] += dp[cur][a][t][c][g]) %= MOD;
        if (ch == 'G' && g + 1 <= G)
          (dp[nxt][a][t][c][g + 1] += dp[cur][a][t][c][g]) %= MOD;
      }
      swap(cur, nxt);
    }
  }
  cout << dp[cur][A][T][C][G] << endl;
}