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

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

bool contains(const string &a, const string &b) {
  if (a.find(b) != string::npos) {
    return true;
  } else
    return false;
}

bool mystrcmp(const string &a, const string &b) { return a.compare(b) < 0; }

bool strless(const string &a, const string &b) {
  if (a.length() < b.length())
    return true;
  else if (a.length() == b.length() && mystrcmp(a, b))
    return true;
  else
    return false;
}

string overwrap(const string &a, const string &b) {
  unsigned int len = 0;
  unsigned int min_len = min(a.length(), b.length());
  string ret = a;

  for (unsigned int i = min_len; i >= 1; --i) {
    bool bOk = true;
    for (unsigned int j = 0; j < i; ++j) {
      if (a[a.length() - i + j] != b[j]) {
        bOk = false;
      }
    }
    if (bOk) {
      len = i;
      break;
    }
  }

  ret += b.c_str() + len;

  return ret;
}

void solve(vector<string> &vs, string &ans) {
  sort(vs.begin(), vs.end(), mystrcmp);

  for (unsigned int i = 0; i < vs.size(); ++i) {
    for (unsigned int j = 0; j < vs.size(); ++j) {
      if (i != j) {
        if (contains(vs[i], vs[j])) {
          vs.erase(vs.begin() + j);
          i = -1;
          break;
        }
      }
    }
  }

  for (unsigned int i = 0; i < vs.size(); ++i) {
    for (unsigned int j = 0; j < vs.size(); ++j) {
      if (i != j) {
        int diff = (vs[i] + vs[j]).length() - (overwrap(vs[i], vs[j])).length();
        if (diff > 0) {
          vector<string> tvs(vs.begin(), vs.end());

          tvs[i] = overwrap(tvs[i], tvs[j]);
          tvs.erase(tvs.begin() + j);
          solve(tvs, ans);
        }
      }
    }
  }

  for (unsigned int i = 1; i < vs.size(); ++i) {
    vs[0] += vs[i];
  }

  if (strless(vs[0], ans))
    ans = vs[0];
}

int main() {
  while (true) {
    int n;
    string ans;
    vector<string> vs;

    scanf("%d", &n);

    if (n == 0)
      break;

    for (int i = 0; i < n; ++i) {
      string s;
      cin >> s;
      vs.push_back(s);
      ans += s;
    }

    solve(vs, ans);

    cout << ans << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#define MAX 10
using namespace std;
bool StrLess(const string &a, const string &b) {
  if (a.length() < b.length())
    return true;
  else if (a.length() == b.length()) {
    return a.compare(b) < 0;
  }
  return false;
}
struct state {
  int last;
  int nUsed;
  string s;
  bool bUsed[MAX];
  bool operator<(const state &t) {
    if (nUsed < t.nUsed) {
      return true;
    } else if (nUsed == t.nUsed) {
      return StrLess(s, t.s);
    }
    return false;
  }
};
bool InsideCommon(const string &a, const string &b) {
  string ta = a, tb = b;
  if (ta.length() < tb.length()) {
    swap(ta, tb);
  }
  if (ta.length() == 0 || tb.length() == 0)
    return false;

  for (unsigned int i = 0; i <= ta.length() - tb.length(); ++i) {
    if (tb == ta.substr(i, tb.length()))
      return true;
  }
  return false;
}
string Overlap(const string &a, const string &b) {
  unsigned int len = 0;
  unsigned int min_len = min(a.length(), b.length());
  string ret = a;

  for (unsigned int i = min_len; i >= 1; --i) {
    bool bOk = true;
    for (unsigned int j = 0; j < i; ++j) {
      if (a[a.length() - i + j] != b[j]) {
        bOk = false;
      }
    }
    if (bOk) {
      len = i;
      break;
    }
  }

  ret += b.c_str() + len;

  return ret;
}
void solve(const vector<string> &vs, state &now, state &best_state) {
  if (now.nUsed == vs.size()) {
    if (now < best_state)
      best_state = now;
  }
  for (unsigned int i = 0; i < vs.size(); ++i) {
    if (!now.bUsed[i]) {
      state t = now;

      if (InsideCommon(t.s, vs[i])) {
        t.bUsed[i] = true;
        ++t.nUsed;
        solve(vs, t, best_state);
        continue;
      }

      t.s = Overlap(t.s, vs[i]);

      if (i < (unsigned)t.last && t.last >= 0) {
        if (vs[t.last].length() == vs[i].length() &&
            (vs[t.last] + vs[i]).length() ==
                Overlap(vs[t.last], vs[i]).length())
          continue;
      }

      ++t.nUsed;
      t.bUsed[i] = true;
      t.last = i;
      if (StrLess(best_state.s, t.s))
        continue;
      solve(vs, t, best_state);
    }
  }
}
int main() {
  while (true) {
    int n;
    state bs;
    state now;
    vector<string> vs;

    scanf("%d", &n);
    if (n == 0)
      break;
    now.nUsed = 0;
    for (int i = 0; i < n; ++i) {
      string s;
      bool bSkip = false;

      now.bUsed[i] = false;
      cin >> s;
      for (unsigned int j = 0; j < vs.size(); ++j) {
        if (InsideCommon(s, vs[j])) {
          bSkip = true;
          break;
        }
      }
      if (bSkip)
        continue;
      vs.push_back(s);
    }
    bs.nUsed = vs.size();

    sort(vs.begin(), vs.end(), StrLess);
    for (unsigned int i = 0; i < vs.size(); ++i) {
      bs.s += vs[i];
    }
    now.last = -1;
    solve(vs, now, bs);

    cout << bs.s << endl;
  }
}