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

#include <algorithm>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toStr(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define REP(i, n) FOR(i, 0, (n)-1)
const double EPS = 1e-12;
const double PI = acos(-1.0);
const int INF = INT_MAX / 10;

string merge(string a, string b) {
  int al = a.length(), bl = b.length();
  string res = a + b;
  FOR(i, 1, min(al, bl)) {
    string as = a.substr(al - i);
    string bs = b.substr(0, i);
    if (as == bs) {
      res = a + b.substr(i);
    }
  }
  return res;
}

int diffstr(string a, string b) { return merge(a, b).length() - a.length(); }

int main() {
  int N;
  while (cin >> N, N) {
    vs data(N);
    REP(i, N) { cin >> data[i]; }

    vs city;
    REP(i, N) {
      bool ok = true;
      REP(j, N) {
        if (i != j && data[j].find(data[i]) != string::npos) {
          ok = false;
          break;
        }
      }
      if (ok) {
        city.push_back(data[i]);
      }
    }

    N = city.size();
    vvi diff(N, vi(N));
    REP(i, N) {
      REP(j, N) { diff[i][j] = diffstr(city[i], city[j]); }
    }

    vvi dp(1 << N, vi(N, INF));
    REP(i, 1 << N) {
      if (i == 0) {
        REP(j, N) { dp[1 << j][j] = city[j].length(); }
        continue;
      }

      REP(j, N) {
        if (i & (1 << j)) {
          REP(k, N) {
            if (j != k && !(i & (1 << k))) {
              dp[i | (1 << k)][k] =
                  min(dp[i | (1 << k)][k], dp[i][j] + diff[j][k]);
            }
          }
        }
      }
    }

    int ans = INF;
    REP(i, N) { ans = min(ans, dp[(1 << N) - 1][i]); }
    cout << ans << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toStr(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define REP(i, n) FOR(i, 0, (n)-1)
const double EPS = 1e-12;
const double PI = acos(-1.0);
const int INF = INT_MAX / 10;

string concat(string a, string b) {
  if (a.find(b) != string::npos) {
    return a;
  }
  if (b.find(a) != string::npos) {
    return b;
  }
  int al = a.length();
  int bl = b.length();
  FOR(i, 1, min(al, bl)) {
    string as = a.substr(al - i);
    string bs = b.substr(0, i);
    if (as == bs) {
      return a + b.substr(i);
    }
  }
  return a + b;
}

int diff(string a, string b) { return concat(a, b).length() - a.length(); }

int dp[1 << 14][14];

int main() {
  int N;
  while (cin >> N, N) {
    vs data(N);
    REP(i, N) { cin >> data[i]; }
    vs city;
    REP(i, N) {
      bool ok = true;
      REP(j, N) {
        if (i != j && data[j].find(data[i]) != string::npos) {
          ok = false;
        }
      }
      if (ok) {
        city.push_back(data[i]);
      }
    }

    N = city.size();
    REP(i, 1 << N) {
      REP(j, N) { dp[i][j] = INF; }
    }
    REP(i, 1 << N) {
      if (i == 0) {
        REP(j, N) { dp[1 << j][j] = city[j].length(); }
        continue;
      }

      REP(j, N) {
        if (i & (1 << j)) {
          REP(k, N) {
            if (!(i & (1 << k)) && j != k) {
              dp[i | (1 << k)][k] =
                  min(dp[i | (1 << k)][k], dp[i][j] + diff(city[j], city[k]));
            }
          }
        }
      }
    }

    int ans = INF;
    REP(i, N) { ans = min(ans, dp[(1 << N) - 1][i]); }
    cout << ans << endl;
  }
}