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

#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <istream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

typedef ostringstream OSS;
typedef istringstream ISS;

typedef vector<int> VI;
typedef vector<VI> VVI;

typedef long long LL;

typedef pair<int, int> PII;
typedef vector<PII> VPII;

#define X first
#define Y second

bool checkCanMerge(string &dist, string &src, int offset) {
  if ((int)dist.size() < offset || (int)src.size() < offset)
    return false;

  for (int i = 0; i < offset; i++) {
    if (dist[dist.size() - offset + i] != src[i]) {
      return false;
    }
  }

  return true;
}

string merge(string dist, string src) {
  if (dist.find(src) != string::npos)
    return dist;
  if (src.find(dist) != string::npos)
    return src;

  for (int offset = min(dist.size(), src.size()); offset >= 0; offset--) {
    if (checkCanMerge(dist, src, offset)) {
      return dist + src.substr(offset, src.size() - offset);
    }
  }

  return dist + src;
}

int main(void) {
  int N;

  while (cin >> N, N) {
    vector<string> ws(N);
    for (auto &w : ws) {
      cin >> w;
    }

    vector<vector<string>> dp(1 << N, vector<string>(N));
    for (int i = 0; i < N; i++) {
      dp[1 << i][i] = ws[i];
    }

    for (int i = 1; i < 1 << N; i++) { // done bit
      for (int j = 0; j < N; j++) {    // before word
        if (!(i & 1 << j))
          continue;

        string dist = dp[i][j];
        if (dist == "")
          continue;

        for (int k = 0; k < N; k++) { // now word
          int next = 1 << k | i;
          if (next == i)
            continue;

          string src = ws[k];
          string merged = merge(dist, src);
          auto &target = dp[next][k];
          //					printf("%d %d %s %s %s %s\\n", i, next,
          //dist.c_str(), src.c_str(), merged.c_str(), target.c_str());

          if (target == "" || target.size() > merged.size()) {
            target = merged;
          } else if (target.size() == merged.size() && target > merged) {
            target = merged;
          }
        }
      }
    }

    string ans = dp.back().back();
    for (auto w : dp.back()) {
      if (ans.size() > w.size()) {
        ans = w;
      } else if (ans.size() == w.size() && ans > w) {
        ans = w;
      }
    }

    cout << ans << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <istream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

typedef ostringstream OSS;
typedef istringstream ISS;

typedef vector<int> VI;
typedef vector<VI> VVI;

typedef long long LL;

typedef pair<int, int> PII;
typedef vector<PII> VPII;

#define X first
#define Y second

bool checkCanMerge(string &dist, string &src, int offset) {
  if (dist.size() < offset || src.size() < offset)
    return false;

  for (int i = 0; i < offset; i++) {
    if (dist[dist.size() - offset + i] != src[i]) {
      return false;
    }
  }

  return true;
}

int main(void) {
  int N;

  while (cin >> N, N) {
    string best;

    vector<string> ws(N);
    for (int i = 0; i < N; i++) {
      cin >> ws[i];
    }

    vector<int> idxes(N);
    iota(idxes.begin(), idxes.end(), 0);

    do {
      string ans;
      for (int i = 0; i < N; i++) { // 10
        string &w = ws[idxes[i]];
        for (int offset = min(ans.size(), w.size()); offset >= 0;
             offset--) {                       // 10
          if (checkCanMerge(ans, w, offset)) { // 10
            ans += w.substr(offset, w.size() - offset);
            break;
          }
        }
      }

      if (best == "" || ans.size() < best.size()) {
        best = ans;
      } else if (ans.size() == best.size() && ans < best) {
        best = ans;
      }
    } while (
        next_permutation(idxes.begin(), idxes.end())); // 10! = 3,628,800 (10^6)

    cout << best << endl;
  }

  return 0;
}