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

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

#define INF (1 << 24)

int common[14][14], N;

bool match(string a, string b, int p) {
  int s = a.size() - 1;

  for (int i = 0; i <= p; i++)
    if (a[s - p + i] != b[i])
      return false;

  return true;
}

int calc(string a, string b) {
  int ret = 0, len = min(a.size(), b.size());

  if (a.find(b, 0) != a.npos)
    return len;

  for (int i = 0; i < len; i++)
    if (match(a, b, i))
      ret = i + 1;

  return ret;
}

bool isUseless(int p, string s, int used) {
  int sz = s.size();
  for (int i = 0; i < N; i++) {
    if (i == p)
      continue;
    if ((used >> i) & 1)
      continue;
    if (common[p][i] == sz || common[i][p] == sz)
      return true;
  }

  return false;
}

string in[14];
int dp[14][1 << 14];

int solve() {
  for (int i = 0; i < N; i++)
    for (int j = 0; j < N; j++)
      common[i][j] = calc(in[i], in[j]);

  int used = 0;
  for (int i = 0; i < N; i++)
    if (isUseless(i, in[i], used))
      used |= (1 << i);

  for (int i = 0; i < N; i++)
    for (int j = 0; j < (1 << N); j++)
      dp[i][j] = INF;

  for (int i = 0; i < N; i++) {
    if ((used >> i) & 1)
      continue;
    dp[i][used | (1 << i)] = in[i].size();
  }

  for (int i = 0; i < (1 << N); i++)
    for (int u = 0; u < N; u++) {
      if (dp[u][i] == INF)
        continue;

      for (int j = 0; j < N; j++) {
        if ((i >> j) & 1)
          continue;

        int cost = in[j].size() - common[u][j];

        dp[j][i | (1 << j)] = min(dp[j][i | (1 << j)], dp[u][i] + cost);
      }
    }

  int res = INF;
  for (int i = 0; i < N; i++)
    res = min(res, dp[i][(1 << N) - 1]);

  return res;
}

int main() {
  while (cin >> N, N) {
    for (int i = 0; i < N; i++)
      cin >> in[i];

    cout << solve() << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

#define INF (1 << 24)

int common[14][14], N;

bool match(string a, string b, int p) {
  int s = a.size() - 1;

  for (int i = 0; i <= p; i++)
    if (a[s - p + i] != b[i])
      return false;

  return true;
}

int calc(string a, string b) {
  int ret = 0, len = min(a.size(), b.size());

  if (a.find(b, 0) != a.npos)
    return len;

  for (int i = 0; i < len; i++)
    if (match(a, b, i))
      ret = i + 1;

  return ret;
}

bool isUseless(int p, string s, int used) {
  int sz = s.size();
  for (int i = 0; i < N; i++) {
    if (i == p)
      continue;
    if ((used >> i) & 1)
      continue;
    if (common[p][i] == sz || common[i][p] == sz)
      return true;
  }

  return false;
}

string in[14];
int dp[14][1 << 14];
string sss[14][1 << 14];

int solve() {
  for (int i = 0; i < N; i++)
    for (int j = 0; j < N; j++)
      common[i][j] = calc(in[i], in[j]);

  int used = 0;
  for (int i = 0; i < N; i++)
    if (isUseless(i, in[i], used))
      used |= (1 << i);

  for (int i = 0; i < N; i++)
    for (int j = 0; j < (1 << N); j++) {
      dp[i][j] = INF;
      sss[i][j] = "";
    }

  for (int i = 0; i < N; i++) {
    if ((used >> i) & 1)
      continue;
    dp[i][used | (1 << i)] = in[i].size();
    sss[i][used | (1 << i)] = in[i];
  }

  for (int i = 0; i < (1 << N); i++)
    for (int u = 0; u < N; u++) {
      if (dp[u][i] == INF)
        continue;

      for (int j = 0; j < N; j++) {
        if ((i >> j) & 1)
          continue;

        string tmp = sss[u][i] + in[j].substr(common[u][j]);
        int cost = in[j].size() - common[u][j];
        if (dp[j][i | (1 << j)] > dp[u][i] + cost ||
            (dp[j][i | (1 << j)] == dp[u][i] + cost &&
             sss[j][i | (1 << j)] > tmp)) {
          dp[j][i | (1 << j)] = dp[u][i] + cost;
          sss[j][i | (1 << j)] = tmp;
        }
      }
    }

  int res = INF;
  for (int i = 0; i < N; i++)
    res = min(res, dp[i][(1 << N) - 1]);

  return res;
}

int main() {
  while (cin >> N, N) {
    for (int i = 0; i < N; i++)
      cin >> in[i];

    cout << solve() << endl;
  }
}