Problem p01329 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

const int INF = 1e8;

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

string D = "DRUL";

const int var = 4;

int trans(char c) {
  switch (c) {
  case 'R':
    return 0;
  case 'D':
    return 1;
  case 'L':
    return 2;
  case 'U':
    return 3;
  default:
    assert(false);
  }
}

struct ac_node {
  ac_node *fail;
  ac_node *next[var];
  vector<int> ok;
  ac_node() : fail(nullptr), next{} {}
};

ac_node *new_ac_node() {
  static const int pmax = 1e3;
  static ac_node pool[pmax];
  static int it = 0;
  assert(it < pmax);
  return &pool[it++];
}

ac_node *getnext(ac_node *p, char c) {
  while (p->next[trans(c)] == nullptr)
    p = p->fail;
  return p->next[trans(c)];
}

class aho_corasick {
  vector<int> unite(const vector<int> &a, const vector<int> &b) {
    vector<int> res;
    set_union(a.begin(), a.end(), b.begin(), b.end(), back_inserter(res));
    return res;
  }
  int K;
  ac_node *root;

public:
  aho_corasick(const vector<string> &Ts) : K(Ts.size()), root(new_ac_node()) {
    ac_node *now;
    root->fail = root;
    for (int i = 0; i < K; i++) {
      auto &T = Ts[i];
      now = root;
      for (auto c : T) {
        if (now->next[trans(c)] == nullptr) {
          now->next[trans(c)] = new_ac_node();
        }
        now = now->next[trans(c)];
      }
      now->ok.push_back(i);
    }
    queue<ac_node *> q;
    for (int i = 0; i < var; i++) {
      if (root->next[i] == nullptr) {
        root->next[i] = root;
      } else {
        root->next[i]->fail = root;
        q.push(root->next[i]);
      }
    }
    while (!q.empty()) {
      now = q.front();
      q.pop();
      for (int i = 0; i < var; i++) {
        if (now->next[i] != nullptr) {
          ac_node *nx = now->fail;
          while (nx->next[i] == nullptr) {
            nx = nx->fail;
          }
          now->next[i]->fail = nx->next[i];
          now->next[i]->ok = unite(now->next[i]->ok, nx->next[i]->ok);
          q.push(now->next[i]);
        }
      }
    }
  }
  ac_node *getroot() const { return root; }
  int get_node_id(ac_node *nd) const { return (int)(nd - root); }
  vector<int> count(const string &S) const {
    vector<int> res(K);
    ac_node *now = root;
    for (auto c : S) {
      now = getnext(now, c);
      for (auto k : now->ok)
        res[k]++;
    }
    return res;
  }
};

using T = tuple<int, int, ac_node *>;

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n, m, p;
  while (cin >> n >> m, n | m) {
    vector<string> S(n);
    int sx = 0, sy = 0, gx = 0, gy = 0;
    for (int i = 0; i < n; i++) {
      cin >> S[i];
      for (int j = 0; j < (int)S[i].size(); j++) {
        if (S[i][j] == 'S') {
          sx = i;
          sy = j;
        } else if (S[i][j] == 'G') {
          gx = i;
          gy = j;
        }
      }
    }
    cin >> p;
    vector<string> pts(p);
    for (int i = 0; i < p; i++) {
      cin >> pts[i];
    }
    aho_corasick aho(pts);
    vector<vector<vector<int>>> f(
        n, vector<vector<int>>(m, vector<int>(200, INF)));
    queue<T> q;
    q.push(make_tuple(sx, sy, aho.getroot()));
    f[sx][sy][aho.get_node_id(aho.getroot())] = 0;
    while (!q.empty()) {
      auto tup = q.front();
      q.pop();
      int x = get<0>(tup), y = get<1>(tup);
      ac_node *nd = get<2>(tup);
      int id = aho.get_node_id(nd);
      for (int i = 0; i < 4; i++) {
        int tx = x + dx[i], ty = y + dy[i];
        ac_node *tnd = getnext(nd, D[i]);
        if (0 <= tx && tx < n && 0 <= ty && ty < m && S[tx][ty] != '#' &&
            tnd->ok.empty() && f[tx][ty][aho.get_node_id(tnd)] == INF) {
          q.push(make_tuple(tx, ty, tnd));
          f[tx][ty][aho.get_node_id(tnd)] = f[x][y][id] + 1;
        }
      }
    }
    int res = INF;
    for (auto val : f[gx][gy]) {
      res = min(res, val);
    }
    cout << (res != INF ? res : -1) << endl;
  }
  return 0;
}


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

const int INF = 1e8;

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

string D = "DRUL";

const int var = 4;

int trans(char c) {
  switch (c) {
  case 'R':
    return 0;
  case 'D':
    return 1;
  case 'L':
    return 2;
  case 'U':
    return 3;
  default:
    assert(false);
  }
}

struct ac_node {
  ac_node *fail;
  ac_node *next[var];
  vector<int> ok;
  ac_node() : fail(nullptr), next{} {}
};

ac_node *new_ac_node() {
  static const int pmax = 1e5;
  static ac_node pool[pmax];
  static int it = 0;
  assert(it < pmax);
  return &pool[it++];
}

ac_node *getnext(ac_node *p, char c) {
  while (p->next[trans(c)] == nullptr)
    p = p->fail;
  return p->next[trans(c)];
}

class aho_corasick {
  vector<int> unite(const vector<int> &a, const vector<int> &b) {
    vector<int> res;
    set_union(a.begin(), a.end(), b.begin(), b.end(), back_inserter(res));
    return res;
  }
  int K;
  ac_node *root;

public:
  aho_corasick(const vector<string> &Ts) : K(Ts.size()), root(new_ac_node()) {
    ac_node *now;
    root->fail = root;
    for (int i = 0; i < K; i++) {
      auto &T = Ts[i];
      now = root;
      for (auto c : T) {
        if (now->next[trans(c)] == nullptr) {
          now->next[trans(c)] = new_ac_node();
        }
        now = now->next[trans(c)];
      }
      now->ok.push_back(i);
    }
    queue<ac_node *> q;
    for (int i = 0; i < var; i++) {
      if (root->next[i] == nullptr) {
        root->next[i] = root;
      } else {
        root->next[i]->fail = root;
        q.push(root->next[i]);
      }
    }
    while (!q.empty()) {
      now = q.front();
      q.pop();
      for (int i = 0; i < var; i++) {
        if (now->next[i] != nullptr) {
          ac_node *nx = now->fail;
          while (nx->next[i] == nullptr) {
            nx = nx->fail;
          }
          now->next[i]->fail = nx->next[i];
          now->next[i]->ok = unite(now->next[i]->ok, nx->next[i]->ok);
          q.push(now->next[i]);
        }
      }
    }
  }
  ac_node *getroot() const { return root; }
  int get_node_id(ac_node *nd) const { return (int)(nd - root); }
  vector<int> count(const string &S) const {
    vector<int> res(K);
    ac_node *now = root;
    for (auto c : S) {
      now = getnext(now, c);
      for (auto k : now->ok)
        res[k]++;
    }
    return res;
  }
};

using T = tuple<int, int, ac_node *>;

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n, m, p;
  while (cin >> n >> m, n | m) {
    vector<string> S(n);
    int sx = 0, sy = 0, gx = 0, gy = 0;
    for (int i = 0; i < n; i++) {
      cin >> S[i];
      for (int j = 0; j < (int)S[i].size(); j++) {
        if (S[i][j] == 'S') {
          sx = i;
          sy = j;
        } else if (S[i][j] == 'G') {
          gx = i;
          gy = j;
        }
      }
    }
    cin >> p;
    vector<string> pts(p);
    for (int i = 0; i < p; i++) {
      cin >> pts[i];
    }
    aho_corasick aho(pts);
    vector<vector<vector<int>>> f(
        n, vector<vector<int>>(m, vector<int>(200, INF)));
    queue<T> q;
    q.push(make_tuple(sx, sy, aho.getroot()));
    f[sx][sy][aho.get_node_id(aho.getroot())] = 0;
    while (!q.empty()) {
      auto tup = q.front();
      q.pop();
      int x = get<0>(tup), y = get<1>(tup);
      ac_node *nd = get<2>(tup);
      int id = aho.get_node_id(nd);
      for (int i = 0; i < 4; i++) {
        int tx = x + dx[i], ty = y + dy[i];
        ac_node *tnd = getnext(nd, D[i]);
        if (0 <= tx && tx < n && 0 <= ty && ty < m && S[tx][ty] != '#' &&
            tnd->ok.empty() && f[tx][ty][aho.get_node_id(tnd)] == INF) {
          q.push(make_tuple(tx, ty, tnd));
          f[tx][ty][aho.get_node_id(tnd)] = f[x][y][id] + 1;
        }
      }
    }
    int res = INF;
    for (auto val : f[gx][gy]) {
      res = min(res, val);
    }
    cout << (res != INF ? res : -1) << endl;
  }
  return 0;
}