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

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

const int INF = 0x3fffffff;

int K;
int N;
char buf[114514];
int match[14][14];
int dp[1 << 14][14];
string tmp[114];
vector<string> names;

bool cmp(const string &a, const string &b) {
  /*if (a.size() != b.size()) */ return a.size() < b.size();
}

bool Contains(string &s, string &p) {
  for (size_t i = 0; i <= s.size() - p.size(); i++) {
    if (s.substr(i, p.size()) == p)
      return true;
  }
  return false;
}

int Match(string &s, string &t) {
  int ret = (int)min(s.size(), t.size());
  while (ret > 0) {
    if (s.substr(s.size() - ret, ret) == t.substr(0, ret))
      return ret;
    ret--;
  }
  return ret;
}

int main() {
  while (1) {
    scanf("%d", &K);
    if (K == 0)
      return 0;

    for (int i = 0; i < K; i++) {
      scanf("%s", buf);
      tmp[i] = buf;
    }
    sort(tmp, tmp + K, cmp);

    names.clear();
    for (int i = 0; i < K; i++) {
      bool found = false;

      for (int j = i + 1; j < K; j++) {
        if (Contains(tmp[j], tmp[i])) {
          found = true;
          break;
        }
      }

      if (!found) {
        names.emplace_back(tmp[i]);
      }
    }

    N = names.size();
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i == j)
          continue;
        match[i][j] = Match(names[i], names[j]);
      }
    }

    int lim = 1 << N;
    fill(dp[0], dp[lim], INF);
    for (int i = 0; i < N; i++) {
      dp[1 << i][i] = names[i].size();
    }

    for (int st = 0; st < lim; st++) {
      for (int i = 0; i < N; i++) {
        if (dp[st][i] == INF)
          continue;
        for (int j = 0; j < N; j++) {
          if (st >> j & 1)
            continue;
          int nst = st | (1 << j);
          int k = match[i][j];
          dp[nst][j] = min(dp[nst][j], dp[st][i] + ((int)names[j].size()) - k);
        }
      }
    }

    int ans = INF;
    for (int i = 0; i < N; i++) {
      ans = min(ans, dp[lim - 1][i]);
    }
    printf("%d\\n", ans);
  }
}


Error: TLE

Fixed submission:

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

const int INF = 0x3fffffff;

int K;
int N;
char buf[114514];
int dp[1 << 14][14];
string tmp[114];
vector<string> names;

bool cmp(const string &a, const string &b) {
  if (a.size() != b.size())
    return a.size() < b.size();
  return a < b;
}

bool Contains(string &s, string &p) {
  for (size_t i = 0; i <= s.size() - p.size(); i++) {
    if (s.substr(i, p.size()) == p)
      return true;
  }
  return false;
}

int Match(string &s, string &t) {
  int ret = (int)min(s.size(), t.size());
  while (ret > 0) {
    if (s.substr(s.size() - ret, ret) == t.substr(0, ret))
      return ret;
    ret--;
  }
  return ret;
}

int main() {
  while (1) {
    scanf("%d", &K);
    if (K == 0)
      return 0;

    for (int i = 0; i < K; i++) {
      scanf("%s", buf);
      tmp[i] = buf;
    }
    sort(tmp, tmp + K, cmp);

    names.clear();
    for (int i = 0; i < K; i++) {
      bool found = false;

      for (int j = i + 1; j < K; j++) {
        if (Contains(tmp[j], tmp[i])) {
          found = true;
          break;
        }
      }

      if (!found) {
        names.emplace_back(tmp[i]);
      }
    }

    N = names.size();
    int lim = 1 << N;
    fill(dp[0], dp[lim], INF);
    for (int i = 0; i < N; i++) {
      dp[1 << i][i] = names[i].size();
    }

    for (int st = 0; st < lim; st++) {
      for (int i = 0; i < N; i++) {
        if (dp[st][i] == INF)
          continue;
        for (int j = 0; j < N; j++) {
          if (st >> j & 1)
            continue;
          int nst = st | (1 << j);
          int k = Match(names[i], names[j]);
          dp[nst][j] = min(dp[nst][j], dp[st][i] + ((int)names[j].size()) - k);
        }
      }
    }

    int ans = INF;
    for (int i = 0; i < N; i++) {
      ans = min(ans, dp[lim - 1][i]);
    }
    printf("%d\\n", ans);
  }
}