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

#include <algorithm>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef vector<PII> VPII;
typedef istringstream ISS;
typedef ostringstream OSS;

#define REP(i, m, n) for (int i = (int)(m); i < (int)(n); ++i)
#define FOR(v, c) for (auto &v : c)
#define EACH(it, c) for (auto it = c.begin(); it != c.end(); ++it)
#define ALL(c) (c).begin(), (c).end()
#define DRANGE(c, p) (c).begin(), (c).begin() + p, (c).end()

#define PB(n) push_back(n)
#define MP(a, b) make_pair((a), (b))
#define EXIST(c, e) ((c).find(e) != (c).end())

#define fst first
#define snd second

#define DUMP(x) cerr << #x << " = " << (x) << endl
#define DEBUG(x)                                                               \\
  cerr << __FILE__ << ":" << __LINE__ << ": " << #x << " = " << (x) << endl

string append(const string &a, const string &b) {
  if (a.find(b) != string::npos) {
    return a;
  }
  if (b.find(a) != string::npos) {
    return b;
  }

  const int L = min(a.size(), b.size());

  for (int l = L; l; l--) {
    if (a.substr(a.size() - l) == b.substr(0, l)) {
      return a + b.substr(l);
    }
  }

  return a + b;
}

struct CompSSS : public binary_function<string, string, bool> {
  bool operator()(const string &a, const string &b) const {
    return a.size() == b.size() ? a < b : a.size() < b.size();
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  for (int n; cin >> n, n;) {
    VS words(n);
    FOR(w, words) { cin >> w; }

    vector<VS> dp(1 << n, VS(n, string(108, '~')));
    REP(i, 0, n) { dp[1 << i][i] = words[i]; }

    REP(bits, 1, 1 << n) {
      REP(i, 0, n) {
        REP(j, 0, n) {
          if (!(bits & 1 << i) || bits & 1 << j) {
            continue;
          }

          dp[bits | 1 << j][j] = min(dp[bits | 1 << j][j],
                                     append(dp[bits][i], words[j]), CompSSS());
        }
      }
    }

    cout << *min_element(ALL(dp.back()), CompSSS()) << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef vector<PII> VPII;
typedef istringstream ISS;
typedef ostringstream OSS;

#define REP(i, m, n) for (int i = (int)(m); i < (int)(n); ++i)
#define FOR(v, c) for (auto &v : c)
#define EACH(it, c) for (auto it = c.begin(); it != c.end(); ++it)
#define ALL(c) (c).begin(), (c).end()
#define DRANGE(c, p) (c).begin(), (c).begin() + p, (c).end()

#define PB(n) push_back(n)
#define MP(a, b) make_pair((a), (b))
#define EXIST(c, e) ((c).find(e) != (c).end())

#define fst first
#define snd second

#define DUMP(x) cerr << #x << " = " << (x) << endl
#define DEBUG(x)                                                               \\
  cerr << __FILE__ << ":" << __LINE__ << ": " << #x << " = " << (x) << endl

int matches(const string &a, const string &b) {
  const int l = min(a.size(), b.size());

  for (int i = l; i; i--) {
    if (a.substr(a.size() - i) == b.substr(0, i)) {
      return i;
    }
  }

  return 0;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  for (int n; cin >> n, n;) {
    VS words(n);
    FOR(w, words) { cin >> w; }
    sort(ALL(words));

    string res(1000, '~');
    do {
      string cur;
      REP(i, 0, n) {
        int l = matches(cur, words[i]);
        cur += words[i].substr(l);
      }

      if (cur.size() == res.size()) {
        res = min(res, cur);
      } else if (cur.size() < res.size()) {
        res = cur;
      }
    } while (next_permutation(ALL(words)));

    cout << res << endl;
  }

  return 0;
}