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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <utility>
#include <vector>

using namespace std;

#define whole(xs) xs.begin(), xs.end()

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "{ ";
  for (int i = 0; i < v.size(); i++) {
    os << v[i] << " ";
  }
  os << "}";
  return os;
}

int N;
vector<string> SS;
int L[10][10];
string cache[10][1 << 10];

int common(const string &s, const string &t) {
  int l = min(s.size(), t.size());
  for (int i = l; i >= 0; i--) {
    bool flag = true;
    for (int j = 0; j < i; j++) {
      if (s[s.size() - i + j] != t[j]) {
        flag = false;
        break;
      }
    }
    if (flag)
      return i;
  }
  assert(0);
}

bool input() {
  cin >> N;
  if (N == 0)
    return false;
  vector<string> v(N);
  SS.clear();
  for (int i = 0; i < N; i++)
    cin >> v[i];
  vector<bool> remove(N, false);
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      if (i == j)
        continue;
      if (v[i] != v[j] && search(whole(v[i]), whole(v[j])) != v[i].end()) {
        remove[j] = true;
      }
    }
  }
  for (int i = 0; i < N; i++) {
    if (!remove[i]) {
      SS.push_back(v[i]);
    }
  }
  N = SS.size();
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      if (i == j)
        continue;
      L[i][j] = common(SS[i], SS[j]);
    }
  }
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < (1 << N); j++) {
      cache[i][j] = "_";
    }
  }
  return true;
}

bool comp(const string &s, const string &t) {
  if (s == "_")
    return false;
  if (t == "_")
    return true;
  if (s.size() == t.size())
    return s < t;
  return s.size() < t.size();
}
#define MIN(s, t) min((s), (t), comp)

string dfs(int v, int used) {
  if (used == (1 << N) - 1)
    return "";
  if (cache[v][used] != "_")
    return cache[v][used];
  string ret = "_";
  for (int i = 0; i < N; i++) {
    if (used & (1 << i))
      continue;
    const string &t = SS[i];
    int l = L[v][i];
    ret = MIN(ret, t.substr(l, t.size() - l) + dfs(i, used | 1 << i));
  }
  return cache[v][used] = ret;
}

int main() {
  while (input()) {
    string ans = "_";
    for (int i = 0; i < N; i++) {
      ans = MIN(ans, SS[i] + dfs(i, 1 << i));
    }
    cout << ans << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <utility>
#include <vector>

using namespace std;

int N;
vector<string> ss;

bool input() {
  cin >> N;
  if (N == 0)
    return false;
  ss.clear();
  ss.resize(N);
  for (int i = 0; i < N; i++) {
    cin >> ss[i];
  }
  return true;
}

string operator*(const string &s, int x) {
  string ret;
  for (int i = 0; i < x; i++) {
    ret += s;
  }
  return ret;
}

string operator^(const string &s, const string &t) {
  int l = min(s.size(), t.size());
  for (int i = l; i >= 0; i--) {
    bool f = true;
    for (int j = 0; j < i; j++) {
      if (s[s.size() - i + j] != t[j]) {
        f = false;
        break;
      }
    }
    if (f) {
      return s.substr(0, s.size() - i) + t;
    }
  }
  assert(false);
}

bool all(const vector<bool> &v) {
  for (int i = 0; i < v.size(); i++) {
    if (!v[i])
      return false;
  }
  return true;
}

ostream &operator<<(ostream &os, vector<bool> &v) {
  os << " {";
  for (int i = 0; i < v.size(); i++) {
    os << " " << v[i];
  }
  os << " } ";
  return os;
}

bool comp(const string &s, const string &t) {
  if (s.size() == t.size())
    return s < t;
  return s.size() < t.size();
}

const string z = string("z") * 100;
string dfs(const string &init, int used) {
  // cerr << init << " " << used;
  if (used == (1 << N) - 1)
    return init;
  string ret = init + z;
  for (int i = 0; i < N; i++) {
    if (used & (1 << i))
      continue;
    int p = used;
    used |= 1 << i;
    ret = min(ret, dfs(init ^ ss[i], used), comp);
    used = p;
  }
  // cerr << ret << endl;
  return ret;
}

int main() {
  while (input()) {
    int used = 0;
    string ans = z;
    for (int i = 0; i < N; i++) {
      int p = used;
      used |= 1 << i;
      ans = min(ans, dfs(ss[i], used), comp);
      used = p;
    }
    cout << ans << endl;
  }
  return 0;
}