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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <utility>
#include <vector>

using namespace std;
int N;
string input[14];
string dp[1 << 14][14];
int cover[14][14];

int solve(const vector<string> &names) {
  int n = names.size();
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (i == j)
        continue;
      cover[i][j] = 0;
      for (int k = min(names[i].size(), names[j].size()) - 1; k > 0; --k) {
        if (names[i].substr(names[i].size() - k) == names[j].substr(0, k)) {
          cover[i][j] = k;
          break;
        }
      }
    }
  }
  for (int i = 0; i < (1 << n); ++i) {
    fill(&dp[i][0], &dp[i][n], string());
  }
  for (int i = 0; i < n; ++i) {
    dp[1 << i][i] = names[i];
  }
  for (int i = 1; i < (1 << n); ++i) {
    for (int j = 0; j < n; ++j) {
      if (dp[i][j].empty())
        continue;
      for (int k = 0; k < n; ++k) {
        if (i & (1 << k))
          continue;
        if (dp[i | (1 << k)][k].empty() ||
            dp[i | (1 << k)][k].size() >
                dp[i][j].size() + names[k].size() - cover[j][k]) {
          dp[i | (1 << k)][k] = dp[i][j] + names[k].substr(cover[j][k]);
        }
      }
    }
  }
  int ret = 999;
  for (int i = 0; i < n; ++i) {
    ret = min(ret, (int)dp[(1 << n) - 1][i].size());
  }
  return ret;
}

int main() {
  while (true) {
    cin >> N;
    if (N == 0)
      break;
    for (int i = 0; i < N; ++i) {
      cin >> input[i];
    }
    vector<string> names;
    for (int i = 0; i < N; ++i) {
      bool contains = false;
      for (int j = 0; j < N; ++j) {
        if (j == i)
          continue;
        if (input[j].find(input[i]) != string::npos) {
          contains = true;
          break;
        }
      }
      if (!contains)
        names.push_back(input[i]);
    }
    cout << solve(names) << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <utility>
#include <vector>

using namespace std;
int N;
string input[14];
string dp[1 << 14][14];

int solve(const vector<string> &names) {
  int n = names.size();
  for (int i = 0; i < (1 << n); ++i) {
    fill(&dp[i][0], &dp[i][n], string());
  }
  for (int i = 0; i < n; ++i) {
    dp[1 << i][i] = names[i];
  }
  for (int i = 1; i < (1 << n); ++i) {
    for (int j = 0; j < n; ++j) {
      if (dp[i][j].empty())
        continue;
      for (int k = 0; k < n; ++k) {
        if (i & (1 << k))
          continue;
        int dup = min(dp[i][j].size(), names[k].size());
        for (; dup > 0; --dup) {
          if (dp[i][j].substr(dp[i][j].size() - dup) == names[k].substr(0, dup))
            break;
        }
        string next = dp[i][j] + names[k].substr(dup);
        if (dp[i | (1 << k)][k].empty() ||
            dp[i | (1 << k)][k].size() > next.size())
          dp[i | (1 << k)][k] = next;
      }
    }
  }
  int ret = 999;
  for (int i = 0; i < n; ++i) {
    ret = min(ret, (int)dp[(1 << n) - 1][i].size());
  }
  return ret;
}

int main() {
  while (true) {
    cin >> N;
    if (N == 0)
      break;
    for (int i = 0; i < N; ++i) {
      cin >> input[i];
    }
    vector<string> names;
    for (int i = 0; i < N; ++i) {
      bool contains = false;
      for (int j = 0; j < N; ++j) {
        if (j == i)
          continue;
        if (input[j].find(input[i]) != string::npos) {
          contains = true;
          break;
        }
      }
      if (!contains)
        names.push_back(input[i]);
    }
    cout << solve(names) << endl;
  }
}