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

#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

typedef vector<string> VS;

const int nsize = 11;
int C[nsize][nsize];
string dp[nsize][1 << nsize];
const string inf = string(nsize * nsize, 'Z');

bool include(string a, string b) {
  // true: a has b
  int as = a.size();
  int bs = b.size();
  if (as < bs)
    return false;
  return a.find(b) != string::npos;
}

VS convert(VS S) {
  VS T;
  set<string> tmp(S.begin(), S.end());
  S = VS(tmp.begin(), tmp.end());
  int n = S.size();
  for (int i = 0; i + 1 < n; ++i) {
    for (int j = i + 1; j < n; ++j) {
      if (S[i].size() == S[j].size()) {
        if (S[i] < S[j]) {
          swap(S[i], S[j]);
        }
      } else {
        if (S[i].size() < S[j].size()) {
          swap(S[i], S[j]);
        }
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    bool flag = true;
    for (int j = 0; j < n; ++j) {
      if (i == j)
        continue;
      if (include(S[j], S[i]))
        flag = false;
    }
    if (flag) {
      T.push_back(S[i]);
    }
  }
  for (int i = 0; i < (int)S.size(); ++i) {
    // cout << "S: " << i << ": " << S[i] << endl;
  }
  for (int i = 0; i < (int)T.size(); ++i) {
    // cout << "T: " << i << ": " << T[i] << endl;
  }
  return T;
}

int calc(string a, string b) {
  int answer = 0;
  int n = min(a.size(), b.size());
  reverse(a.begin(), a.end());
  for (int i = 0; i <= n; ++i) {
    string s = a.substr(0, i);
    reverse(s.begin(), s.end());
    if (s == b.substr(0, i)) {
      answer = max(answer, i);
    }
  }
  return answer;
}

string get_sub(string s, int c) { return s.substr(c); }

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

bool check(string a, string b) {
  if (a.size() == b.size()) {
    return a >= b;
  } else {
    return a.size() >= b.size();
  }
}

string min_element_str(VS W) {
  int n = W.size();
  for (int i = 0; i + 1 < n; ++i) {
    for (int j = i + 1; j < n; ++j) {
      if (check(W[i], W[j])) {
        swap(W[i], W[j]);
      }
    }
  }
  return W[0];
}

int main() {
  int n;
  while (cin >> n && n) {
    VS W;
    string w;
    for (int i = 0; i < n; ++i) {
      cin >> w;
      W.push_back(w);
    }

    W = convert(W);
    n = W.size();
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        C[i][j] = calc(W[i], W[j]);
      }
    }

    int m = 1 << n;
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < m; ++j) {
        dp[i][j] = inf;
      }
    }
    for (int i = 0; i < n; ++i) {
      dp[i][1 << i] = W[i];
    }
    for (int i = 0; i < m; ++i) {   // state
      for (int j = 0; j < n; ++j) { // prev
        if (dp[j][i] == inf)
          continue;
        for (int k = 0; k < n; ++k) { // next
          if (i & 1 << k)
            continue;
          int s = i;
          int ns = i | 1 << k;
          string t = dp[j][s] + get_sub(W[k], C[j][k]);
          dp[k][ns] = min_str(dp[k][ns], t);
        }
      }
    }
    string answer = inf;
    for (int i = 0; i < n; ++i) {
      answer = min_str(answer, dp[i][m - 1]);
    }
    cout << answer << "\\n";
  }
  return 0;
}

Error: TLE

Fixed submission:

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

#define INF (1 << 21)

int main(void) {
  int n;
  while (cin >> n && n) {
    vector<string> words;
    string word;
    for (int i = 0; i < n; i++) {
      cin >> word;
      words.push_back(word);
    }
    sort(words.begin(), words.end());

    vector<string> sss;
    int min_length = INF;
    do {
      vector<string> work = words;
      string crypt = "";
      for (vector<string>::iterator it = work.begin(); it != work.end(); it++) {
        if (it == work.begin())
          crypt += *it;
        else {
          string w = *it;
          string reverse_crypt = crypt;
          reverse(reverse_crypt.begin(), reverse_crypt.end());
          int i;
          string w_cut;
          for (int j = w.size(); j >= 1; j--) {
            w_cut = w.substr(0, j);
            reverse(w_cut.begin(), w_cut.end());
            for (i = 0; i < w_cut.size(); i++) {
              if (i >= crypt.size())
                break;
              if (w_cut[i] != reverse_crypt[i])
                break;
            }
            if (i >= w_cut.size())
              break;
          }
          crypt += (*it).substr(i);
        }
      }

      if (min_length == INF) {
        min_length = crypt.size();
        sss.push_back(crypt);
      } else if (min_length == crypt.size()) {
        sss.push_back(crypt);
      } else if (min_length > crypt.size()) {
        sss = vector<string>();
        min_length = crypt.size();
        sss.push_back(crypt);
      }
    } while (next_permutation(words.begin(), words.end()));

    sort(sss.begin(), sss.end());
    cout << sss[0] << endl;
  }

  return 0;
}