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

#include <bits/stdc++.h>
using namespace std;
int N;
string s[15];
vector<string> S;
int mar[15][15];
int dp[(1 << 15)][15];

int marge(int a, int b) {
  for (int i = 0; i < (int)S[a].size(); i++) {
    bool f = true;
    for (int j = 0; j < (int)S[b].size() && i + j < (int)S[a].size(); j++) {
      if (S[b][j] != S[a][i + j])
        f = false;
      if (!f)
        break;
    }
    if (f) {
      if (i + S[b].size() <= S[a].size())
        return 0;
      return (int)S[b].size() - (S[a].size() - i);
    }
  }
  return (int)S[b].size();
}
bool contain(int a, int b) {
  if (s[a].size() < s[b].size())
    return false;
  for (int i = 0; i < (int)s[a].size() - (int)s[b].size() + 1; i++) {
    if (s[a].substr(i, (int)s[b].size()) == s[b])
      return true;
  }
  return false;
}
#define INF (1 << 29)
int main() {
  while (cin >> N && N) {
    for (int i = 0; i < N; i++) {
      cin >> s[i];
    }
    bool used[15] = {};
    for (int i = 0; i < N; i++)
      for (int j = 0; j < N; j++)
        if (i != j && contain(i, j))
          used[j] = true;

    S.clear();
    for (int i = 0; i < N; i++)
      if (!used[i])
        S.push_back(s[i]);
    N = S.size();

    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        mar[i][j] = marge(i, j);
      }
    }
    for (int i = 0; i < N; i++)
      mar[N][i] = S[i].size();
    fill(dp[0], dp[(1 << N)], INF);
    dp[0][N] = 0;
    int res = INF;
    for (int i = 0; i < (1 << N); i++) {
      for (int j = 0; j <= N; j++) {
        if (i == (1 << N) - 1)
          res = min(res, dp[i][j]);
        if (dp[i][j] == INF)
          continue;
        for (int k = 0; k < N; k++) {
          if (i & (1 << k))
            continue;
          dp[i | (1 << k)][k] = min(dp[i | (1 << k)][k], dp[i][j] + mar[j][k]);
        }
      }
    }
    cout << res << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

#define INF (1 << 29)
int N;
string s[15];
int dp[(1 << 15)][16];
string sdp[(1 << 15)][16];
int result = INF;

string compare(const string &a, const string &b) {
  string ret = "";
  for (int i = a.size() - b.size(); i < (int)a.size(); i++) {
    bool f = false;
    for (int j = 0; j < (int)b.size() && i + j < (int)a.size(); j++) {
      if (a[i + j] != b[j]) {
        f = true;
        break;
      }
    }
    if (!f) {
      ret = a.substr(0, i) + b;
      break;
    }
  }
  if (ret == "")
    ret = a + b;
  //  cout <<a << " "<< b << " " << ret << endl;
  return ret;
}
vector<string> compareV(string a, string b) {
  vector<string> ret;
  ret.push_back(compare(a, b));
  ret.push_back(compare(b, a));
  if (a.size() < b.size())
    swap(a, b);

  for (int i = 0; i < (int)a.size() - (int)b.size() + 1; i++) {
    bool f = false;
    for (int j = 0; j < (int)b.size(); j++) {
      if (a[i + j] != b[j]) {
        f = true;
        break;
      }
    }
    if (!f) {
      ret.push_back(a);
      break;
    }
  }
  return ret;
}

int solve(const string &str, int st, int id) {
  if (dp[st][id] != -1)
    return dp[st][id];
  if (st == (1 << N) - 1) {
    //  cout << str << endl;
    result = min(result, (int)str.size());
    return dp[st][id] = str.size();
  }
  //   cout << str << endl;
  int ret = INF;
  for (int i = 0; i < N; i++) {
    if (st & (1 << i))
      continue;
    vector<string> vec = compareV(str, s[i]);
    for (int j = 0; j < (int)vec.size(); j++) {
      if ((int)vec[j].size() >= result)
        continue;
      ret = min(ret, solve(vec[j], st | (1 << i), i));
    }
  }
  return dp[st][id] = ret;
}

int solve() {
  result = INF;
  fill(dp[0], dp[(1 << N)], INF);
  dp[0][N] = 0;
  sdp[0][N] = "";
  for (int st = 0; st < (1 << N); st++) {
    for (int id = 0; id <= N; id++) {
      if (dp[st][id] == INF)
        continue;
      if (st == (1 << N) - 1) {
        //  cout << str << endl;
        result = min(result, (int)sdp[st][id].size());
      }
      for (int i = 0; i < N; i++) {
        if (st & (1 << i))
          continue;
        vector<string> vec = compareV(sdp[st][id], s[i]);
        for (int j = 0; j < (int)vec.size(); j++) {
          int ms = vec[j].size();
          if (ms >= result)
            continue;
          if (ms < dp[st | (1 << i)][i]) {
            dp[st | (1 << i)][i] = ms;
            sdp[st | (1 << i)][i] = vec[j];
          }
        }
      }
    }
  }
  //   cout << str << endl;
  return result;
}

int main() {
  while (cin >> N && N) {
    for (int i = 0; i < N; i++) {
      cin >> s[i];
    }
    string str = "";
    cout << solve() << endl;
  }
}