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

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
#include <string>
#include <utility>
#include <vector>
using namespace std;

#define rep(i, n) for (int i = 0; i < n; i++)
#define reps(i, s, n) for (int i = s; i < n; i++)
#define all(x) x.begin(), x.end()
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int INF = 1 << 30;

int cost[10][10];
string dp[1 << 10][10];

bool comp(string s1, string s2) {
  if (s1.length() == s2.length())
    return s1 < s2;
  else
    return s1.length() < s2.length();
}

int cntTwice(string out, string w) {
  if (out.length() >= w.length()) {
    for (int j = w.length() - 1; j > 0; j--) {
      string s1 = out.substr(out.length() - j, j);
      string s2 = w.substr(0, j);
      if (s1 == s2) {
        return j;
      }
    }
  } else {
    for (int j = 0; j < out.length(); j++) {
      string s1 = out.substr(j, out.length() - j);
      string s2 = w.substr(0, out.length() - j);
      if (s1 == s2) {
        return out.length() - j;
      }
    }
  }
  return 0;
}

int main() {
  int n;
  while (cin >> n, n) {
    vector<string> inw(n);
    rep(i, n) { cin >> inw[i]; }
    bool inner[10] = {};
    rep(i, n) {
      if (inner[i])
        continue;
      rep(j, n) {
        if (i != j && !inner[j] && inw[i].find(inw[j]) != string::npos) {
          inner[j] = true;
        }
      }
    }
    vector<string> word;
    rep(i, n) {
      if (!inner[i])
        word.push_back(inw[i]);
    }
    n = word.size();

    rep(i, n) rep(j, n) cost[i][j] = cntTwice(word[i], word[j]);
    rep(i, (1 << n)) rep(j, n) dp[i][j] = "";
    rep(i, n) dp[1 << i][i] = word[i];
    for (int i = 0; i < (1 << n); i++) {
      for (int p = 0; p < n; p++) {
        for (int j = 0; j < n; j++) {
          if (!(i & (1 << j)) && p != j && dp[i][p] != "") {
            if (dp[i | (1 << j)][j] == "")
              dp[i | (1 << j)][j] = dp[i][p] + word[j].substr(cost[p][j]);
            else {
              if (comp(dp[i | (1 << j)][j],
                       dp[i][p] + word[j].substr(cost[p][j])))
                dp[i | (1 << j)][j] = dp[i | (1 << j)][j];
              else
                dp[i | (1 << j)][j] = dp[i][p] + word[j].substr(cost[p][j]);
            }
          }
        }
      }
    }
    vector<string> ans;
    rep(i, n) ans.push_back(dp[(1 << n) - 1][i]);
    sort(ans.begin(), ans.end(), comp);
    cout << ans[0] << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

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

#define rep(i, n) for (int i = 0; i < n; i++)
#define reps(i, s, n) for (int i = s; i < n; i++)
#define all(x) x.begin(), x.end()
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

bool comp(string s1, string s2) {
  if (s1.length() == s2.length())
    return s1 < s2;
  else
    return s1.length() < s2.length();
}

int main() {
  int n;
  while (cin >> n, n) {
    vector<string> word(n);
    rep(i, n) { cin >> word[i]; }
    sort(word.begin(), word.end());
    string res = "";
    do {
      string out = word[0];
      for (int i = 1; i < n; i++) {
        if (out.length() >= word[i].length()) {
          bool in = false;
          if (out.find(word[i]) != string::npos)
            in = true;
          if (!in) {
            for (int j = word[i].length() - 1; j > 0; j--) {
              string s1 = out.substr(out.length() - j, j);
              string s2 = word[i].substr(0, j);
              if (s1 == s2) {
                in = true;
                out += word[i].substr(j, word[i].length() - j);
                break;
              }
            }
          }
          if (!in) {
            out += word[i];
          }
        } else {
          bool found = false;
          for (int j = 0; j < out.length(); j++) {
            string s1 = out.substr(j, out.length() - j);
            string s2 = word[i].substr(0, out.length() - j);
            if (s1 == s2) {
              found = true;
              out += word[i].substr(out.length() - j,
                                    word[i].length() - out.length() + j);
              break;
            }
          }
          if (!found) {
            out += word[i];
          }
        }
      }
      if (res == "" || comp(out, res)) {
        res = out;
      }
    } while (next_permutation(word.begin(), word.end()));
    cout << res << endl;
  }
  return 0;
}