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

#include <bits/stdc++.h>

using namespace std;

struct acam {
  const static int kind = 26;
  const static int len = 300;
  int fail[len];
  int next[len][kind];
  int counts[len];
  int q[len];
  int head, tail;
  int poolsize;
  int root;

  void clear();
  inline int newnode();
  int insert(char *str, int tag);
  void build_ac_automation();

} ac;

void acam::clear() {
  memset(fail, 0, sizeof(fail));
  memset(next, 0, sizeof(next));
  memset(counts, 0, sizeof(counts));
  poolsize = 1;
  root = 1;
}

inline int acam::newnode() { return ++poolsize; }

int acam::insert(char *str, int tag) {
  int cnt = root;
  for (int i = 0; str[i]; i++) {
    int index = str[i] - 'A';
    if (!next[cnt][index])
      next[cnt][index] = newnode();
    cnt = next[cnt][index];
  }
  counts[cnt] |= (1 << tag);
  return cnt;
}

void acam::build_ac_automation() {
  head = tail = 0;
  fail[root] = root;
  q[tail++] = root;
  while (head != tail) {
    int cnt = q[head++];
    counts[cnt] |= counts[fail[cnt]];
    for (int i = 0; i < kind; i++) {
      if (next[cnt][i]) {
        counts[next[cnt][i]] |= counts[cnt];
        if (cnt == root)
          fail[next[cnt][i]] = root;
        else
          fail[next[cnt][i]] = next[fail[cnt]][i];
        q[tail++] = next[cnt][i];
      } else if (cnt == root)
        next[cnt][i] = root;
      else
        next[cnt][i] = next[fail[cnt]][i];
    }
  }
}

char str[100010];

int dp[300][1 << 14];
int went[300][1 << 14];
int status[30];

queue<pair<int, int>> que;

int dist[300][300];

int main() {
  int n;
  // freopen("1.txt","r" ,stdin);
  // freopen("output.txt", "w" ,stdout);
  while (scanf("%d", &n) == 1) {
    if (n == 0)
      break;
    ac.clear();
    for (int i = 1; i <= n; i++) {
      scanf("%s", str);
      status[i] = ac.insert(str, i - 1);
    }
    ac.build_ac_automation();
    memset(dist, -1, sizeof(dist));
    for (int i = 1; i <= ac.poolsize; i++)
      for (int j = 0; j < ac.kind; j++)
        dist[i][ac.next[i][j]] = 1;
    for (int i = 1; i <= ac.poolsize; i++)
      dist[i][i] = 0;
    for (int k = 1; k <= ac.poolsize; k++)
      for (int i = 1; i <= ac.poolsize; i++)
        for (int j = 1; j <= ac.poolsize; j++)
          if (dist[i][k] != -1 && dist[k][j] != -1)
            if (dist[i][j] == -1 || dist[i][k] + dist[k][j] < dist[i][j])
              dist[i][j] = dist[i][k] + dist[k][j];
    /*
    printf("       ");
    for (int i=0; i<ac.kind; i++)
        printf("%2c ", 'a'+i);
    printf("\\n");
    for (int i=1; i<=ac.poolsize; i++)
    {
        printf("%2d %2d: ", i, ac.counts[i]);
        for (int j=0; j<ac.kind; j++)
            printf("%2d ", ac.next[i][j]);
        printf("\\n");
    }
    */

    /*
    memset(dp, -1, sizeof(dp));
    memset(went, 0, sizeof(went));
    */
    int finish = (1 << n) - 1;
    for (int i = 1; i <= ac.poolsize; i++)
      for (int j = 0; j <= finish; j++)
        dp[i][j] = -1, went[i][j] = 0;
    while (!que.empty()) {
      que.pop();
    }

    que.push(make_pair(1, ac.counts[1]));
    /*
    for (int i=1; i<=n; i++)
        printf("%d ", status[i]);
    printf("\\n");
    for (int i = 1; i<=n; i++)
    {
        printf("%d ", dist[1][status[i]]);
        for (int j=1; j<=n; j++)
            printf("%d ", dist[status[i]][status[j]]);
        printf("\\n");
    }
    */

    // printf("%d\\n", que.size());
    went[1][ac.counts[1]] = 1;
    dp[1][0] = 0;
    int ans = -1;
    while (!que.empty()) {
      pair<int, int> cnt = que.front();
      went[cnt.first][cnt.second] = 0;
      que.pop();
      for (int i = 1; i <= n; i++) {
        int nextsta = status[i];
        if (dist[cnt.first][nextsta] != -1) {
          pair<int, int> nextt =
              make_pair(nextsta, cnt.second | ac.counts[nextsta]);
          if (dp[nextt.first][nextt.second] == -1 ||
              dp[nextt.first][nextt.second] >
                  dp[cnt.first][cnt.second] + dist[cnt.first][nextsta]) {
            dp[nextt.first][nextt.second] =
                dp[cnt.first][cnt.second] + dist[cnt.first][nextsta];
            if (finish == nextt.second) {
              if (ans == -1 || ans > dp[nextt.first][nextt.second])
                ans = dp[nextt.first][nextt.second];
            }

            if (!went[nextt.first][nextt.second]) {
              went[nextt.first][nextt.second] = 1;
              que.push(nextt);
            }
          }
        }
      }
    }
    printf("%d\\n", ans);
  }
  return 0;
}

Error: TLE

Fixed submission:

/*
Author: 1412kid1412@UESTC
*/

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <utility>
#include <valarray>
#include <vector>
using namespace std;

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

char str[15][22];

int trie[301][26];
int flag[301];
int total;

void init() {
  memset(flag, 0, sizeof(flag));
  memset(trie[0], 0, sizeof(trie[0]));
  total = 0;
}

void insert(char str[], int idx) {
  int len = strlen(str);
  int now = 0;
  for (int i = 0; i < len; i++) {
    int ind = str[i] - 'A';
    if (!trie[now][ind]) {
      total++;
      memset(trie[total], 0, sizeof(trie[total]));
      trie[now][ind] = total;
    }
    now = trie[now][ind];
  }
  flag[now] = (1 << idx);
}

int f[300];
int solve(int n) {
  queue<int> que;
  f[0] = 0;

  memset(dp, 63, sizeof(dp));
  for (int i = 0; i < 26; i++) {
    if (trie[0][i]) {
      que.push(trie[0][i]);
      f[trie[0][i]] = 0;
    }
  }

  while (!que.empty()) {
    int u = que.front();
    que.pop();
    for (int i = 0; i < 26; i++) {
      if (trie[u][i]) {
        int v = trie[u][i];
        que.push(v);
        f[v] = trie[f[u]][i];
        flag[v] |= flag[f[v]];
      } else {
        trie[u][i] = trie[f[u]][i];
      }
    }
  }

  memset(inq, 0, sizeof(inq));
  memset(dp, 63, sizeof(dp));
  int ret = dp[0][0];
  dp[0][0] = 0;
  inq[0][0] = 1;

  queue<pair<int, int>> q;
  q.push(make_pair(0, 0));
  while (!q.empty()) {
    pair<int, int> u = q.front();
    q.pop();
    inq[u.first][u.second] = 0;
    for (int l = 0; l < 26; l++) {
      int v = trie[u.first][l];
      if (dp[v][u.second | flag[v]] > dp[u.first][u.second] + 1) {
        dp[v][u.second | flag[v]] = dp[u.first][u.second] + 1;
        if (!inq[v][u.second | flag[v]]) {
          inq[v][u.second | flag[v]] = true;
          q.push(make_pair(v, u.second | flag[v]));
        }
      }
    }
  }
  for (int i = 0; i <= total; i++) {
    ret = min(ret, dp[i][(1 << n) - 1]);
  }
  return ret;
}

int main() {
  int n;
  while (scanf("%d", &n) && n) {
    init();
    for (int i = 0; i < n; i++) {
      scanf("%s", str[i]);
      insert(str[i], i);
    }
    printf("%d\\n", solve(n));
  }
  return 0;
}