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

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

#define REP(i, n) for (int i = 0; i < n; ++i)

struct SuffixArray {
  struct SAComp {
    const int h;
    const vector<int> &g;
    SAComp(const int h_, const vector<int> &g_) : h(h_), g(g_) { ; }
    bool operator()(int a, int b) {
      return a == b ? false : g[a] != g[b] ? g[a] < g[b] : g[a + h] < g[b + h];
    }
  };

  static const int SIZE = 100000;
  int n;
  string str;
  vector<int> sa;
  vector<int> lcp;

  SuffixArray() { ; }
  SuffixArray(const string t) : str(t) { Init(); }
  void Init() {
    n = str.size();
    buildSA();
    buildLCP();
  }

  // O(mlogn)

  ////バグあるかも
  // int find(const string p) {
  //	int m = p.size();
  //	int left = 0;
  //	int right = n-m;
  //	while (left < right) {
  //		int mid = (left + right) / 2;
  //		if (str.substr(sa[mid],m)<p.substr(0,m)) { left = mid + 1; }
  //		else { right = mid; }
  //	}
  //	return str.substr(sa[left], m)== p.substr(0, m)? sa[left] : -1;
  // }
private:
  // O(nlog^2n)
  void buildSA() {
    sa = vector<int>(n + 1);
    vector<int> g(n + 1);
    vector<int> b(n + 1);
    REP(i, n + 1) {
      sa[i] = i;
      g[i] = str[i];
    }
    b[0] = 0;
    b[n] = 0;
    SAComp f(0, g);
    sort(sa.begin(), sa.end(), SAComp(0, g));
    for (int h = 1; b[n] != n; h *= 2) {
      SAComp comp(h, g);
      sort(sa.begin(), sa.end(), comp);
      REP(i, n) b[i + 1] = b[i] + comp(sa[i], sa[i + 1]);
      REP(i, n + 1) g[sa[i]] = b[i];
    }
  }
  void buildLCP() {
    lcp = vector<int>(n + 1);
    int h = 0;
    vector<int> b(n + 1);
    REP(i, n + 1) { b[sa[i]] = i; }
    REP(i, n + 1) {
      if (b[i]) {
        for (int j = sa[b[i] - 1];
             j + h < n && i + h < n && str[j + h] == str[i + h]; h++) {
          ;
        }
        lcp[b[i]] = h;
      } else {
        lcp[b[i]] = -1;
      }
      if (h > 0) {
        h--;
      }
    }
  }

public:
  //[l..r)がtestから始まる
  pair<int, int> getlr(string test) {
    pair<int, int> p;
    {
      int amin = 0;
      int amax = str.size() + 1;
      while (amin + 1 != amax) {
        int amid((amin + amax) / 2);
        string name = str.substr(sa[amid], test.size());
        if (name < test) {
          amin = amid;
        } else {
          amax = amid;
        }
      }
      p.first = amax;
    }
    {
      int amin = 0;
      int amax = str.size() + 1;
      while (amin + 1 != amax) {
        int amid((amin + amax + 1) / 2);
        string name = str.substr(sa[amid], test.size());
        if (name <= test) {
          amin = amid;
        } else {
          amax = amid;
        }
      }
      p.second = amax;
    }
    return p;
  }
};

int N, M;
bool solve(const int now, const vector<vector<int>> &oks, bitset<12> &used,
           vector<string> &words, vector<int> &dp) {
  if (dp[used.to_ulong()])
    return false;
  dp[used.to_ulong()] = true;
  if (used.count() == N)
    return true;
  else {
    for (int i = 0; i < N; ++i) {
      if (!used[i] && oks[now][i]) {
        used[i] = true;
        if (solve(now + words[i].size(), oks, used, words, dp))
          return true;
        used[i] = false;
      }
    }
  }
  return false;
}
int main() {
  while (true) {
    cin >> N >> M;
    if (N == 0 && M == 0)
      break;
    vector<string> words;
    for (int i = 0; i < N; ++i) {
      string st;
      cin >> st;
      words.push_back(st);
    }
    string str;
    for (int i = 0; i < M; ++i) {
      string st;
      cin >> st;
      str += st;
    }
    SuffixArray sa(str);

    vector<vector<int>> oks(str.size() + 1, vector<int>(N));
    for (int i = 0; i < N; ++i) {
      string word(words[i]);
      int al, ar;
      auto p(sa.getlr(word));
      al = p.first;
      ar = p.second;
      for (int x = al; x < ar; ++x) {
        oks[sa.sa[x]][i] = true;
      }
    }

    int len_sum = 0;
    for (int i = 0; i < N; ++i)
      len_sum += words[i].size();
    int ans = 0;
    for (int i = 0; i <= int(str.size()) - len_sum; ++i) {
      bitset<12> bs;
      vector<int> dp(1 << 12);
      if (solve(i, oks, bs, words, dp))
        ans++;
    }
    cout << ans << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

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

int main() {
  int n, m;
  while (cin >> n >> m, n) {
    vector<string> e(n);
    string t;
    for (int i = 0; i < n; ++i) {
      cin >> e[i];
    }
    for (int i = 0; i < m; ++i) {
      string tt;
      cin >> tt;
      t += tt;
    }

    int const T = t.size();
    vector<vector<bool>> match(T, vector<bool>(n));
    for (int i = 0; i < T; ++i) {
      for (int j = 0; j < n; ++j) {
        if (e[j].size() + i > T) {
          continue;
        }
        match[i][j] = t.substr(i, e[j].size()) == e[j];
      }
    }

    vector<vector<char>> dp(T + 1, vector<char>(1 << n));
    for (int i = 0; i < T; ++i) {
      dp[i][0] = 1;
    }
    for (int i = 0; i < T; ++i) {
      for (int S = 0; S < (1 << n); ++S) {
        for (int j = 0; j < n; ++j) {
          if (S & (1 << j) || !match[i][j]) {
            continue;
          }
          int len = e[j].size();
          if (dp[i + len][S | (1 << j)] != 0) {
            continue;
          }
          dp[i + len][S | (1 << j)] += dp[i][S];
        }
      }
    }

    int res = 0;
    for (int i = 0; i <= T; ++i) {
      res += dp[i][(1 << n) - 1];
    }
    cout << res << endl;
  }
}