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

#include <bits/stdc++.h>
using namespace std;
#define INF                                                                    \\
  "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" \\
  "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"

string chmin(string a, string b) {
  if (a.size() != b.size())
    return (a.size() < b.size() ? a : b);
  return (a < b ? a : b);
}

int main() {
  string dp1[10][10], dp2[10][1 << 10];
  int n;
  vector<string> str;

  while (cin >> n, n) {
    fill_n(*dp1, 10 * 10, INF);
    fill_n(*dp2, 10 * 1 << 10, INF);
    str.resize(n);
    for (int i = 0; i < n; i++) {
      cin >> str[i];
    }
    unsigned bit = 0u;
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (i == j || (bit >> i) & 1 || (bit >> j) & 1)
          continue;
        if (str[i].find(str[j]) != string::npos)
          bit |= 1 << j;
      }
    }

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        dp1[i][j] = str[j];
        if ((bit >> i) & 1 || (bit >> j) & 1)
          continue;
        for (int k = 0; k < str[i].size(); k++) {
          if (str[i].substr(k) == str[j].substr(0, str[i].substr(k).size())) {
            dp1[i][j] = str[j].substr(str[i].substr(k).size());
            break;
          }
        }
      }
    }

    for (int i = 0; i < n; i++) {
      dp2[i][bit | (1 << i)] = str[i];
    }
    for (int i = 0; i < 1 << n; i++) {
      for (int j = 0; j < n; j++) {
        if (dp2[j][i | bit] == INF)
          continue;
        for (int k = 0; k < n; k++) {
          if (j == k || ((i | bit) >> k) & 1)
            continue; // mumumu??
          dp2[k][i | bit | (1 << k)] =
              chmin(dp2[k][i | bit | (1 << k)], dp2[j][i | bit] + dp1[j][k]);
        }
      }
    }
    string ret = INF;
    for (int i = 0; i < n; i++) {
      ret = chmin(ret, dp2[i][(1 << n) - 1]);
    }

    cout << ret << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define INF                                                                    \\
  "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" \\
  "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" \\
  "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"

int n;
string str[16];
string ret;

string chmin(string a, string b) {
  if (a.size() < b.size())
    return a;
  if (a.size() > b.size())
    return b;
  return (a < b ? a : b);
}
map<int, string> dp;

string rec(string s, int used) {
  if (dp.find(used) != dp.end() && chmin(dp[used], s) != s) {
    return dp[used];
  }

  if (chmin(s, ret) != s)
    return INF;
  if (__builtin_popcount(used) == n)
    return s;
  string ret = INF;
  for (int i = 0; i < n; i++) {
    if (used >> i & 1)
      continue;
    // さのぴさーんはかわいーい
    if (s.find(str[i]) != string::npos)
      return rec(s, used | (1 << i));
    for (int j = 0; j < min(s.size(), str[i].size());
         j++) { // これは次の文字をどれだけ食い込ませるか
      bool flag = true;
      for (int k = 0; k < j; k++) {
        if (s[s.size() - j + k] != str[i][k]) {
          flag = false;
          break;
        }
      }
      if (flag)
        ret = chmin(ret, rec(s + str[i].substr(j), used | (1 << i)));
    }
  }
  return dp[used] = ret;
}

int main() {
  while (cin >> n, n) {
    ret = INF;
    for (int i = 0; i < n; i++) {
      cin >> str[i];
    }

    for (int i = 0; i < n; i++) {
      ret = chmin(ret, rec(str[i], 1 << i));
    }

    cout << ret << endl;

    dp.clear();
  }
  return (0);
}