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

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

const int MAX = 14;
const int INF = 1e8;

int N;
int d[MAX][MAX];

int dp[1 << MAX][MAX];

int rec(int S, int v) {
  if (dp[S][v] >= 0) {
    return dp[S][v];
  }

  if (S == (1 << N) - 1) {
    return dp[S][v] = 0;
  }

  int res = INF;
  for (int u = 0; u < N; u++) {
    if (!(S >> u & 1)) {
      res = min(res, rec(S | 1 << u, u) + d[v][u]);
    }
  }
  return dp[S][v] = res;
}

int main() {
  while (cin >> N, N) {
    vector<string> c(N);
    for (int i = 0; i < N; i++) {
      cin >> c[i];
    }

    vector<string> erase;
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i != j) {
          if (c[i].find(c[j]) != string::npos) {
            if (c[i].size() > c[j].size() && c[i].size() <= 20) {
              erase.push_back(c[j]);
            } else {
              erase.push_back(c[i]);
            }
          }
        }
      }
    }

    for (int i = 0; i < erase.size(); i++) {
      for (int j = 0; j < c.size(); j++) {
        if (erase[i] == c[j]) {
          c.erase(c.begin() + j);
          break;
        }
      }
    }

    /**
    for (int i=0; i<c.size(); i++) {
            cerr << c[i] << endl;
    } **/

    N = c.size();
    fill(d[0], d[0] + MAX * MAX, INF);
    memset(dp, -1, sizeof(dp));

    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i != j) {
          string f = c[i], t = c[j];
          int tmp = 0;
          for (int a = 0; a < f.size(); a++) {
            bool ok = true;
            for (int b = 0; b < a; b++) {
              if (b >= t.size() || f[f.size() - a + b] != t[b]) {
                ok = false;
              }
            }
            if (ok)
              tmp = max(tmp, a);
          }
          d[i][j] = min((int)t.size() - tmp, d[i][j]);
        }
      }
    }

    /**
    for (int i=0; i<N; i++) {
            for (int j=0; j<N; j++) {
                    cerr<<d[i][j]<< " ";
            }
            cerr << endl;
    } **/

    int res = INF;
    for (int u = 0; u < N; u++) {
      res = min(res, rec(1 << u, u) + (int)c[u].size());
    }

    cout << res << endl;
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

const int MAX = 14;
const int INF = 1e8;

int N;
int d[MAX][MAX];

int dp[1 << MAX][1 << MAX];

int rec(int S, int v) {
  if (dp[S][v] >= 0) {
    return dp[S][v];
  }

  if (S == (1 << N) - 1) {
    return dp[S][v] = 0;
  }

  int res = INF;
  for (int u = 0; u < N; u++) {
    if (!(S >> u & 1)) {
      res = min(res, rec(S | 1 << u, u) + d[v][u]);
    }
  }
  return dp[S][v] = res;
}

int main() {
  while (cin >> N, N) {
    vector<string> c(N);
    for (int i = 0; i < N; i++) {
      cin >> c[i];
    }

    fill(d[0], d[0] + MAX * MAX, INF);
    memset(dp, -1, sizeof(dp));

    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i != j) {
          if (c[i].find(c[j]) != string::npos) {
            d[i][j] = d[j][i] = 0;
            if (c[i].size() > c[j].size()) {
              c[j] = "hogehogehogehogehogehoge";
            } else {
              c[i] = "hogehogehogehogehogehoge";
            }
          }
        }
      }
    }

    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i != j) {
          string f = c[i], t = c[j];
          int tmp = 0;
          for (int a = 0; a < f.size(); a++) {
            bool ok = true;
            for (int b = 0; b < a; b++) {
              if (b >= t.size() || f[f.size() - a + b] != t[b]) {
                ok = false;
              }
            }
            if (ok)
              tmp = max(tmp, a);
          }
          d[i][j] = min((int)t.size() - tmp, d[i][j]);
        }
      }
    }

    /**
    for (int i=0; i<N; i++) {
            for (int j=0; j<N; j++) {
                    cerr<<d[i][j]<< " ";
            }
            cerr << endl;
    } **/

    int res = INF;
    for (int u = 0; u < N; u++) {
      res = min(res, rec(1 << u, u) + (int)c[u].size());
    }

    cout << res << endl;
  }
}