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

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <vector>

#define pb push_back
#define mp make_pair

using namespace std;

char s[15][25];
int calc[15][15];
bool flag[15];
int list[15], cnt;
int n, N;
int len[15];
int dp[1 << 15][15];

int gao(int x, int y) {
  int lenx = strlen(s[x]), leny = strlen(s[y]);
  int ret = 0;
  for (int i = 1; lenx - i >= 0 && i - 1 < leny; i++) {
    bool flag = true;
    for (int j = 0; j <= i - 1; j++)
      if (s[y][j] != s[x][lenx - i + j])
        flag = false;
    if (flag)
      ret = max(ret, i);
  }
  return ret;
}

bool inside(int x, int y) {
  int lenx = strlen(s[x]), leny = strlen(s[y]);
  if (lenx > leny)
    return false;
  bool flag = false;
  for (int i = 0; i <= leny - lenx; i++) {
    bool same = true;
    for (int j = 0; j < lenx; j++)
      if (s[x][j] != s[y][j + i])
        same = false;
    if (same)
      flag = true;
  }
  return flag;
}

void prework() {
  // s[i]s[j]
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      if (i != j)
        calc[i][j] = gao(i, j);
}

int main() {

  // freopen("input.txt","r",stdin);

  while (~scanf("%d", &n) && n) {
    for (int i = 0; i < n; i++)
      scanf("%s", s[i]), flag[i] = true;

    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        if (i != j && inside(i, j))
          flag[i] = false;

    N = 0;
    for (int i = 0; i < n; i++)
      if (flag[i])
        list[N++] = i;

    for (int i = 0; i < n; i++)
      len[i] = strlen(s[i]);
    prework();

    for (int i = 0; i < (1 << N); i++)
      for (int j = 0; j < N; j++)
        dp[i][j] = 0x3F3F3F3F;

    for (int i = 0; i < N; i++)
      dp[1 << i][i] = len[list[i]];
    for (int i = 1; i < (1 << N); i++) {
      for (int j = 0; j < N; j++)
        if ((i >> j) & 1)
          for (int k = 0; k < N; k++)
            if (!((i >> k) & 1))
              dp[i | (1 << k)][k] =
                  min(dp[i | (1 << k)][k],
                      dp[i][j] + len[list[k]] - calc[list[k]][list[j]]);
    }

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

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>

using namespace std;

const int kind = 26;
int sz;
const int maxn = 20 * 14 + 10;

struct node {
  int word, fail, ch[kind];
  int pre() {
    fail = word = 0;
    memset(ch, 0, sizeof(ch));
    return sz;
  }
} trie[maxn];

void init() {
  sz = 0;
  trie[0].pre();
}

void built(char str[], int id) {
  int p = 0, k = 0, idx;
  for (; str[k]; k++) {
    idx = str[k] - 'A';
    if (trie[p].ch[idx] == 0)
      trie[p].ch[idx] = trie[++sz].pre();
    p = trie[p].ch[idx];
  }
  trie[p].word |= 1 << id;
}

void BFS_AC() {
  queue<int> Q;
  while (!Q.empty())
    Q.pop();
  Q.push(0);
  int temp, son, p;
  while (!Q.empty()) {
    temp = Q.front();
    trie[temp].word |= trie[trie[temp].fail].word;
    Q.pop();
    for (int i = 0; i < kind; i++) {
      if (trie[temp].ch[i] > 0) {
        son = trie[temp].ch[i];
        Q.push(son);
        if (temp == 0)
          continue;
        p = trie[temp].fail;
        trie[son].fail = trie[p].ch[i];
      } else {
        if (temp == 0)
          continue;
        trie[temp].ch[i] = trie[trie[temp].fail].ch[i];
      }
    }
  }
}

int n;
char s[30];
int dp[maxn][1 << 14];
int maxx;
int vis[maxn][1 << 14];

int main() {
  memset(vis, 0, sizeof(vis));
  for (int cas = 1; scanf("%d", &n) == 1 && n; cas++) {
    init();
    for (int i = 0; i < n; i++) {
      scanf("%s", s);
      built(s, i);
    }
    BFS_AC();
    maxx = 1 << n;
    static int i, j;
    for (i = 0; i <= sz; i++)
      for (j = 0; j < maxx; j++)
        dp[i][j] = maxn;
    dp[0][trie[0].word] = 0;
    static queue<int> Q;
    static int a, b, c, d;
    while (!Q.empty())
      Q.pop();
    Q.push(0);
    Q.push(trie[0].word);
    while (!Q.empty()) {
      a = Q.front();
      Q.pop();
      b = Q.front();
      Q.pop();
      vis[a][b] = 0;
      for (i = 0; i < 26; i++) {
        c = trie[a].ch[i];
        d = b | trie[c].word;
        if (dp[a][b] + 1 < dp[c][d]) {
          dp[c][d] = dp[a][b] + 1;
          if (vis[c][d] != cas) {
            vis[c][d] = cas;
            Q.push(c);
            Q.push(d);
          }
        }
      }
    }
    static int ans;
    ans = maxn;
    for (i = 0; i <= sz; i++)
      if (dp[i][maxx - 1] < ans)
        ans = dp[i][maxx - 1];
    printf("%d\\n", ans);
  }
  return 0;
}