Problem p00772 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <deque>
#include <vector>
// #include <windows.h>

using namespace std;

char dp[50][51][50][51], dp2[2][50][51][60][10], dp3[2][50][51][31];
short visited1[50][51][50][51], visited2[2][50][51][60][10],
    visited3[2][50][51][31];
vector<int> trans[60];
vector<int> transHash[31];
vector<int> reqLength[2][50][31];

deque<int> inp[2];
int n, m, r;

int caseN;

char transPossible(int, int, int, int, int);

char canConvergeTo(int type, int s, int e, int tarnum) {
  if (s >= e)
    return 0;
  char &ret = dp3[type][s][e][tarnum];
  if (visited3[type][s][e][tarnum])
    return ret;

  ret = 0;
  for (int i = 0; i < transHash[tarnum].size(); i++) {
    int ntind = transHash[tarnum][i];
    if (transPossible(type, s, e, ntind, 0))
      return ret = 1;
  }

  return ret;
}

char transPossible(int type, int s, int e, int ttype, int tind) {
  if (trans[ttype].size() == tind) {
    if (s == e)
      return 1;
    return 0;
  }
  if (s >= e)
    return 0;
  if (e - s < (int)trans[ttype].size() - tind)
    return 0;

  char &ret = dp2[type][s][e][ttype][tind];
  if (visited2[type][s][e][ttype][tind] == caseN)
    return ret;
  visited2[type][s][e][ttype][tind] = caseN;

  ret = 0;
  if (inp[type][s] == trans[ttype][tind] &&
      transPossible(type, s + 1, e, ttype, tind + 1))
    return ret = 1;
  int tar = trans[ttype][tind],
      shouldLeft = (int)trans[ttype].size() - tind - 1;
  for (int i = s + 1; i <= e - shouldLeft; i++)
    if (canConvergeTo(type, s, i, tar) &&
        transPossible(type, i, e, ttype, tind + 1))
      return ret = 1;

  return ret;
}

char getAns(int s1, int e1, int s2, int e2) {
  if (s1 == e1 && s2 == e2)
    return 0;
  if (s1 >= e1 || s2 >= e2)
    return -2;

  char &ret = dp[s1][e1][s2][e2];
  if (visited1[s1][e1][s2][e2] == caseN)
    return ret;
  visited1[s1][e1][s2][e2] = caseN;

  ret = -2;
  int v1 = inp[0][s1], v2 = inp[1][s2];
  char res;

  if (v1 == v2 && (res = getAns(s1 + 1, e1, s2 + 1, e2)) != -2)
    ret = max(ret, (char)(res + 1));

  for (int i = 0; i < reqLength[1][s2][v1].size(); i++) {
    int req = reqLength[1][s2][v1][i];
    if ((res = getAns(s1 + 1, e1, s2 + req, e2)) != -2)
      ret = max(ret, (char)(res + 1));
  }

  for (int i = 0; i < reqLength[0][s1][v2].size(); i++) {
    int req = reqLength[0][s1][v2][i];
    if ((res = getAns(s1 + req, e1, s2 + 1, e2)) != -2)
      ret = max(ret, (char)(res + 1));
  }

  for (int tv = 0; tv <= 30; tv++) {
    for (int i = 0;
         i < reqLength[0][s1][tv].size() && s1 + reqLength[0][s1][tv][i] <= e1;
         i++)
      for (int j = 0; j < reqLength[1][s2][tv].size() &&
                      s2 + reqLength[1][s2][tv][j] <= e2;
           j++) {
        int req1 = reqLength[0][s1][tv][i];
        int req2 = reqLength[1][s2][tv][j];
        if ((res = getAns(s1 + req1, e1, s2 + req2, e2)) != -2)
          ret = max(ret, (char)(res + 1));
      }
  }
  return ret;
}

int main(void) {
  while (scanf("%d %d %d", &n, &m, &r), n) {
    caseN++;

    inp[0].resize(n), inp[1].resize(m);
    for (int i = 0; i < n; i++)
      scanf("%d", &inp[0][i]);
    for (int i = 0; i < m; i++)
      scanf("%d", &inp[1][i]);
    for (int i = 0; i < n; i++)
      inp[0].push_back(inp[0][i]);
    for (int i = 0; i < m; i++)
      inp[1].push_back(inp[1][i]);

    for (int i = 0; i <= 30; i++)
      transHash[i].clear();
    for (int i = 0; i < r; i++) {
      int K;
      scanf("%d", &K);
      trans[i].resize(K);
      for (int j = 0; j < K; j++)
        scanf("%d", &trans[i][j]);
      int to;
      scanf("%d", &to);
      transHash[to].push_back(i);
    }

    int ans = -1;

    //		int curTime = GetTickCount();

    for (int i = 0; i < 50; i++)
      for (int j = 0; j <= 30; j++)
        reqLength[0][i][j].clear(), reqLength[1][i][j].clear();

    for (int i = 0; i < n * 2; i++)
      for (int j = i + 2; j <= n * 2; j++)
        for (int k = 0; k <= 30; k++) {
          vector<int> &tar = reqLength[0][i][k];
          for (int q = 0; q < transHash[k].size(); q++) {
            int ti = transHash[k][q];
            if (transPossible(0, i, j, ti, 0))
              tar.push_back(j - i);
          }
          sort(tar.begin(), tar.end());
          tar.erase(unique(tar.begin(), tar.end()), tar.end());
        }

    for (int i = 0; i < m * 2; i++)
      for (int j = i + 2; j <= m * 2; j++)
        for (int k = 0; k <= 30; k++) {
          vector<int> &tar = reqLength[1][i][k];
          for (int q = 0; q < transHash[k].size(); q++) {
            int ti = transHash[k][q];
            if (transPossible(1, i, j, ti, 0))
              reqLength[1][i][k].push_back(j - i);
          }
          sort(tar.begin(), tar.end());
          tar.erase(unique(tar.begin(), tar.end()), tar.end());
        }

    //		fprintf(stderr, "%d, ", GetTickCount() - curTime);
    //		curTime = GetTickCount();

    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++)
        ans = max((char)ans, getAns(i, i + n, j, j + m));

    //		fprintf(stderr, "%d\\n", GetTickCount() - curTime);

    printf("%d\\n", ans);
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <deque>
#include <vector>
// #include <windows.h>

using namespace std;

int dp[50][51][50][51], dp2[2][50][51][60][10], dp3[2][50][51][31];
int visited1[50][51][50][51], visited2[2][50][51][60][10],
    visited3[2][50][51][31];
vector<int> trans[60];
vector<int> transHash[31];
vector<int> reqLength[2][50][31];

deque<int> inp[2];
int n, m, r;

int caseN;

int transPossible(int, int, int, int, int);

int canConvergeTo(int type, int s, int e, int tarnum) {
  if (s >= e)
    return 0;
  int &ret = dp3[type][s][e][tarnum];
  if (visited3[type][s][e][tarnum])
    return ret;

  ret = 0;
  for (int i = 0; i < transHash[tarnum].size(); i++) {
    int ntind = transHash[tarnum][i];
    if (transPossible(type, s, e, ntind, 0))
      return ret = 1;
  }

  return ret;
}

int transPossible(int type, int s, int e, int ttype, int tind) {
  if (trans[ttype].size() == tind) {
    if (s == e)
      return 1;
    return 0;
  }
  if (s >= e)
    return 0;
  if (e - s < (int)trans[ttype].size() - tind)
    return 0;

  int &ret = dp2[type][s][e][ttype][tind];
  if (visited2[type][s][e][ttype][tind] == caseN)
    return ret;
  visited2[type][s][e][ttype][tind] = caseN;

  ret = 0;
  if (inp[type][s] == trans[ttype][tind] &&
      transPossible(type, s + 1, e, ttype, tind + 1))
    return ret = 1;
  int tar = trans[ttype][tind],
      shouldLeft = (int)trans[ttype].size() - tind - 1;
  for (int i = s + 1; i <= e - shouldLeft; i++)
    if (canConvergeTo(type, s, i, tar) &&
        transPossible(type, i, e, ttype, tind + 1))
      return ret = 1;

  return ret;
}

int getAns(int s1, int e1, int s2, int e2) {
  if (s1 == e1 && s2 == e2)
    return 0;
  if (s1 >= e1 || s2 >= e2)
    return -2;

  int &ret = dp[s1][e1][s2][e2];
  if (visited1[s1][e1][s2][e2] == caseN)
    return ret;
  visited1[s1][e1][s2][e2] = caseN;

  ret = -2;
  int v1 = inp[0][s1], v2 = inp[1][s2];
  int res;

  if (v1 == v2 && (res = getAns(s1 + 1, e1, s2 + 1, e2)) != -2)
    ret = max(ret, res + 1);

  for (int i = 0; i < reqLength[1][s2][v1].size(); i++) {
    int req = reqLength[1][s2][v1][i];
    if ((res = getAns(s1 + 1, e1, s2 + req, e2)) != -2)
      ret = max(ret, res + 1);
  }

  for (int i = 0; i < reqLength[0][s1][v2].size(); i++) {
    int req = reqLength[0][s1][v2][i];
    if ((res = getAns(s1 + req, e1, s2 + 1, e2)) != -2)
      ret = max(ret, res + 1);
  }

  for (int tv = 0; tv <= 30; tv++) {
    for (int i = 0;
         i < reqLength[0][s1][tv].size() && s1 + reqLength[0][s1][tv][i] <= e1;
         i++)
      for (int j = 0; j < reqLength[1][s2][tv].size() &&
                      s2 + reqLength[1][s2][tv][j] <= e2;
           j++) {
        int req1 = reqLength[0][s1][tv][i];
        int req2 = reqLength[1][s2][tv][j];
        if ((res = getAns(s1 + req1, e1, s2 + req2, e2)) != -2)
          ret = max(ret, res + 1);
      }
  }
  return ret;
}

int main(void) {
  while (scanf("%d %d %d", &n, &m, &r), n) {
    caseN++;

    inp[0].resize(n), inp[1].resize(m);
    for (int i = 0; i < n; i++)
      scanf("%d", &inp[0][i]);
    for (int i = 0; i < m; i++)
      scanf("%d", &inp[1][i]);
    for (int i = 0; i < n; i++)
      inp[0].push_back(inp[0][i]);
    for (int i = 0; i < m; i++)
      inp[1].push_back(inp[1][i]);

    for (int i = 0; i <= 30; i++)
      transHash[i].clear();
    for (int i = 0; i < r; i++) {
      int K;
      scanf("%d", &K);
      trans[i].resize(K);
      for (int j = 0; j < K; j++)
        scanf("%d", &trans[i][j]);
      int to;
      scanf("%d", &to);
      transHash[to].push_back(i);
    }

    int ans = -1;

    //		int curTime = GetTickCount();

    for (int i = 0; i < 50; i++)
      for (int j = 0; j <= 30; j++)
        reqLength[0][i][j].clear(), reqLength[1][i][j].clear();

    for (int i = 0; i < n * 2; i++)
      for (int j = i + 2; j <= n * 2; j++)
        for (int k = 0; k <= 30; k++) {
          vector<int> &tar = reqLength[0][i][k];
          for (int q = 0; q < transHash[k].size(); q++) {
            int ti = transHash[k][q];
            if (transPossible(0, i, j, ti, 0))
              tar.push_back(j - i);
          }
          sort(tar.begin(), tar.end());
          tar.erase(unique(tar.begin(), tar.end()), tar.end());
        }

    for (int i = 0; i < m * 2; i++)
      for (int j = i + 2; j <= m * 2; j++)
        for (int k = 0; k <= 30; k++) {
          vector<int> &tar = reqLength[1][i][k];
          for (int q = 0; q < transHash[k].size(); q++) {
            int ti = transHash[k][q];
            if (transPossible(1, i, j, ti, 0))
              reqLength[1][i][k].push_back(j - i);
          }
          sort(tar.begin(), tar.end());
          tar.erase(unique(tar.begin(), tar.end()), tar.end());
        }

    //		fprintf(stderr, "%d, ", GetTickCount() - curTime);
    //		curTime = GetTickCount();

    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++)
        ans = max(ans, getAns(i, i + n, j, j + m));

    //		fprintf(stderr, "%d\\n", GetTickCount() - curTime);

    printf("%d\\n", ans);
  }

  return 0;
}