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

#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#define MOD 1000000007LL

using namespace std;

typedef long long ll;
typedef string::const_iterator State;
typedef pair<int, int> P;
int n[4];
int all;
int m;
string str[51];
map<string, int> ind;
vector<P> vec[51];
vector<int> rule;
ll dp[2][51][51][51][51];

void make_rule(int v) {
  if (all < rule.size())
    return;
  for (int i = 0; i < vec[v].size(); i++) {
    if (vec[v][i].first == 0) {
      rule.push_back(vec[v][i].second);
    } else {
      make_rule(vec[v][i].second);
    }
  }
}

void parse_2(State &begin, State &end, int par) {
  if (*begin == ' ')
    begin++;
  if (begin == end)
    return;
  if (*begin == '[') {
    begin++;
    int bit = 0;
    while (*begin != ']') {
      if (*begin == 'A')
        bit |= (1 << 0);
      if (*begin == 'T')
        bit |= (1 << 1);
      if (*begin == 'G')
        bit |= (1 << 2);
      if (*begin == 'C')
        bit |= (1 << 3);
      begin++;
    }
    begin++;
    vec[par].push_back(P(0, bit));
  } else {
    string st = "";
    while (*begin != ' ' && begin != end) {
      st += *begin;
      begin++;
    }
    if (ind.find(st) == ind.end()) {
      int next = ind.size();
      ind[st] = next;
    }
    vec[par].push_back(P(1, ind[st]));
  }
  parse_2(begin, end, par);
  return;
}

void parse_1(State &begin, State &end) {
  string st = "";
  while (*begin != ':') {
    st += *begin;
    begin++;
  }
  if (ind.find(st) == ind.end()) {
    int next = ind.size();
    ind[st] = next;
  }
  int par = ind[st];
  begin++;
  begin++;
  parse_2(begin, end, par);
  return;
}

int main(void) {
  for (int i = 0; i < 4; i++) {
    scanf("%d", &n[i]);
    all += n[i];
  }
  scanf("%d%*c", &m);

  for (int i = 0; i < m; i++) {
    getline(cin, str[i]);
    State begin = str[i].begin();
    State end = str[i].end();
    parse_1(begin, end);
  }
  make_rule(0);
  int prev = 0, now = 1;
  dp[prev][0][0][0][0] = 1;
  for (int i = 0; i < rule.size(); i++) {
    int g[4];
    for (g[0] = 0; g[0] <= n[0]; g[0]++) {
      if (g[0] > i)
        continue;
      for (g[1] = 0; g[1] <= n[1]; g[1]++) {
        if (g[0] + g[1] > i)
          continue;
        for (g[2] = 0; g[2] <= n[2]; g[2]++) {
          if (g[0] + g[1] + g[2] > i)
            continue;
          for (g[3] = 0; g[3] <= n[3]; g[3]++) {
            if (g[0] + g[1] + g[2] + g[3] > i)
              continue;
            if (dp[prev][g[0]][g[1]][g[2]][g[3]] >= 1) {
              if ((rule[i] >> 0 & 1) && g[0] + 1 <= n[0]) {
                dp[now][g[0] + 1][g[1]][g[2]][g[3]] +=
                    dp[prev][g[0]][g[1]][g[2]][g[3]];
                if (dp[now][g[0] + 1][g[1]][g[2]][g[3]] >= MOD)
                  dp[now][g[0] + 1][g[1]][g[2]][g[3]] -= MOD;
              }
              if ((rule[i] >> 1 & 1) && g[1] + 1 <= n[1]) {
                dp[now][g[0]][g[1] + 1][g[2]][g[3]] +=
                    dp[prev][g[0]][g[1]][g[2]][g[3]];
                if (dp[now][g[0]][g[1] + 1][g[2]][g[3]] >= MOD)
                  dp[now][g[0]][g[1] + 1][g[2]][g[3]] -= MOD;
              }
              if ((rule[i] >> 2 & 1) && g[2] + 1 <= n[2]) {
                dp[now][g[0]][g[1]][g[2] + 1][g[3]] +=
                    dp[prev][g[0]][g[1]][g[2]][g[3]];
                if (dp[now][g[0]][g[1]][g[2] + 1][g[3]] >= MOD)
                  dp[now][g[0]][g[1]][g[2] + 1][g[3]] -= MOD;
              }
              if ((rule[i] >> 3 & 1) && g[3] + 1 <= n[3]) {
                dp[now][g[0]][g[1]][g[2]][g[3] + 1] +=
                    dp[prev][g[0]][g[1]][g[2]][g[3]];
                if (dp[now][g[0]][g[1]][g[2]][g[3] + 1] >= MOD)
                  dp[now][g[0]][g[1]][g[2]][g[3] + 1] -= MOD;
              }
            }
          }
        }
      }
    }
    swap(now, prev);
    memset(dp[now], 0, sizeof(dp[now]));
  }
  printf("%lld\\n", dp[prev][n[0]][n[1]][n[2]][n[3]]);
  return 0;
}

Error: TLE

Fixed submission:

#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#define MOD 1000000007LL

using namespace std;

typedef long long ll;
typedef string::const_iterator State;
typedef pair<int, int> P;
int n[4];
int all;
int m;
string str[51];
map<string, int> ind;
vector<P> vec[51];
vector<int> rule;
ll dp[2][51][51][51][51];

void make_rule(int v) {
  if (all < rule.size())
    return;
  for (int i = 0; i < vec[v].size(); i++) {
    if (vec[v][i].first == 0) {
      rule.push_back(vec[v][i].second);
    } else {
      make_rule(vec[v][i].second);
    }
  }
}

void parse_2(State &begin, State &end, int par) {
  if (*begin == ' ')
    begin++;
  if (begin == end)
    return;
  if (*begin == '[') {
    begin++;
    int bit = 0;
    while (*begin != ']') {
      if (*begin == 'A')
        bit |= (1 << 0);
      if (*begin == 'T')
        bit |= (1 << 1);
      if (*begin == 'G')
        bit |= (1 << 2);
      if (*begin == 'C')
        bit |= (1 << 3);
      begin++;
    }
    begin++;
    vec[par].push_back(P(0, bit));
  } else {
    string st = "";
    while (*begin != ' ' && begin != end) {
      st += *begin;
      begin++;
    }
    if (ind.find(st) == ind.end()) {
      int next = ind.size();
      ind[st] = next;
    }
    vec[par].push_back(P(1, ind[st]));
  }
  parse_2(begin, end, par);
  return;
}

void parse_1(State &begin, State &end) {
  string st = "";
  while (*begin != ':') {
    st += *begin;
    begin++;
  }
  if (ind.find(st) == ind.end()) {
    int next = ind.size();
    ind[st] = next;
  }
  int par = ind[st];
  begin++;
  begin++;
  parse_2(begin, end, par);
  return;
}

int main(void) {
  for (int i = 0; i < 4; i++) {
    scanf("%d", &n[i]);
    all += n[i];
  }
  scanf("%d%*c", &m);

  for (int i = 0; i < m; i++) {
    getline(cin, str[i]);
    State begin = str[i].begin();
    State end = str[i].end();
    parse_1(begin, end);
  }
  make_rule(0);
  int prev = 0, now = 1;
  dp[prev][0][0][0][0] = 1;
  for (int i = 0; i < rule.size(); i++) {
    int g[4];
    for (g[0] = 0; g[0] <= n[0]; g[0]++) {
      for (g[1] = 0; g[1] <= n[1]; g[1]++) {
        for (g[2] = 0; g[2] <= n[2]; g[2]++) {
          for (g[3] = 0; g[3] <= n[3]; g[3]++) {
            dp[prev][g[0]][g[1]][g[2]][g[3]] %= MOD;
            if (dp[prev][g[0]][g[1]][g[2]][g[3]] >= 1) {
              if ((rule[i] >> 0 & 1) && g[0] + 1 <= n[0]) {
                dp[now][g[0] + 1][g[1]][g[2]][g[3]] +=
                    dp[prev][g[0]][g[1]][g[2]][g[3]];
              }
              if ((rule[i] >> 1 & 1) && g[1] + 1 <= n[1]) {
                dp[now][g[0]][g[1] + 1][g[2]][g[3]] +=
                    dp[prev][g[0]][g[1]][g[2]][g[3]];
              }
              if ((rule[i] >> 2 & 1) && g[2] + 1 <= n[2]) {
                dp[now][g[0]][g[1]][g[2] + 1][g[3]] +=
                    dp[prev][g[0]][g[1]][g[2]][g[3]];
              }
              if ((rule[i] >> 3 & 1) && g[3] + 1 <= n[3]) {
                dp[now][g[0]][g[1]][g[2]][g[3] + 1] +=
                    dp[prev][g[0]][g[1]][g[2]][g[3]];
              }
            }
          }
        }
      }
    }
    swap(now, prev);
    memset(dp[now], 0, sizeof(dp[now]));
  }
  printf("%lld\\n", dp[prev][n[0]][n[1]][n[2]][n[3]] % MOD);
  return 0;
}