Problem p01329 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

#define each(i, a) for (auto &&i : a)
#define FOR(i, a, b) for (ll i = (a), __last_##i = (b); i < __last_##i; i++)
#define RFOR(i, a, b) for (ll i = (b)-1, __last_##i = (a); i >= __last_##i; i--)
#define REP(i, n) FOR(i, 0, n)
#define RREP(i, n) RFOR(i, 0, n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define all(a) (a).begin(), (a).end()
#define chmin(x, v) x = min(x, v)
#define chmax(x, v) x = max(x, v)

const ll linf = 1e18;
const double eps = 1e-12;
const double pi = acos(-1);

template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  each(x, vec) is >> x;
  return is;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  rep(i, vec.size()) {
    if (i)
      os << " ";
    os << vec[i];
  }
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<vector<T>> &vec) {
  rep(i, vec.size()) {
    if (i)
      os << endl;
    os << vec[i];
  }
  return os;
}
class AhoCorasick {
  void clear_graph() {
    root.child.clear();
    root.pattern.clear();
  }
  void generate_trie(const vector<string> &patterns) {
    ll n = patterns.size();
    rep(i, n) {
      Node *t = &root;
      each(c, patterns[i]) {
        if (t->child.count(c) == 0) {
          t->child[c] = Node(nodes.size());
          nodes.pb(&t->child[c]);
        }
        t = &(t->child[c]);
      }
      t->pattern.push_back(i);
    }
  }
  void add_failure_edge() {
    queue<Node *> Q;
    Q.push(&root);
    // 幅優先探索で帰納的に失敗時の遷移辺を追加していく
    while (!Q.empty()) {
      Node *t = Q.front();
      Q.pop();
      each(p, t->child) {
        Q.push(&(p.second));
        char c = p.first;
        Node *node = &(p.second); // 文字cで遷移する頂点
        Node *anode = t->failure; // 失敗したときの遷移先
        while (anode != NULL && anode->child.count(c) == 0) {
          anode = anode->failure;
        }
        // 遷移失敗時に続けられる別の頂点へ遷移
        if (anode == NULL) {
          node->failure = &root;
        } else {
          node->failure = &(anode->child[c]);
        }
        // マッチするパターンを追加
        each(to, node->failure->pattern) { node->pattern.pb(to); }
        // メモリ食いすぎ回避のため切り詰めておく
        vector<size_t>(node->pattern).swap(node->pattern);
      }
    }
  }
  // Pattern Match Automatonを構築
  void make_PMA(const vector<string> &patterns) {
    clear_graph();
    generate_trie(patterns);
    add_failure_edge();
  }

public:
  struct Node {
    ll id;
    map<char, Node> child;  // 遷移辺(!)
    vector<size_t> pattern; // マッチするパターン(のindex)
    Node *failure;          // 遷移失敗時の遷移先ノード
    Node() : failure(NULL) {}
    Node(ll id) : failure(NULL), id(id) {}
  };
  vector<Node *> nodes;
  Node root;
  AhoCorasick(const vector<string> &patterns) : nodes(0), root(0) {
    nodes.assign(1, &root);
    make_PMA(patterns);
  }
  pair<Node *, vector<ll>> find(Node *node, char c) {
    vector<ll> res;
    while (node != NULL && node->child.count(c) == 0) {
      node = node->failure;
    }
    if (node == NULL)
      node = &root;
    else
      node = &(node->child[c]);
    each(ptn, node->pattern) { res.pb(ptn); }
    return pair<Node *, vector<ll>>(node, res);
  }
};

const string dname = "URDL";
const ll dx[] = {0, 1, 0, -1};
const ll dy[] = {-1, 0, 1, 0};

struct Node2 {
  ll x, y, nid;
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  ll h, w;
  while (cin >> h >> w, h || w) {
    vector<string> m(h);
    cin >> m;
    ll patterns;
    cin >> patterns;
    vector<string> ptn(patterns);
    cin >> ptn;
    AhoCorasick ac(ptn);
    auto inRange = [&](ll x, ll y) {
      return 0 <= x && x < w && 0 <= y && y < h;
    };
    ll sx, sy, gx, gy;
    rep(y, h) rep(x, w) {
      if (m[y][x] == 'S')
        sx = x, sy = y;
      if (m[y][x] == 'G')
        gx = x, gy = y;
    }
    ll n = ac.nodes.size();
    vector<vector<vector<ll>>> dist(h,
                                    vector<vector<ll>>(w, vector<ll>(n, linf)));
    queue<Node2> Q;
    dist[sy][sx][0] = 0;
    Q.push({sx, sy, 0});
    while (!Q.empty()) {
      Node2 node = Q.front();
      Q.pop();
      ll x = node.x, y = node.y, nid = node.nid;
      AhoCorasick::Node *ac_node = ac.nodes[nid];
      rep(d, 4) {
        ll nx = x + dx[d];
        ll ny = y + dy[d];
        if (!inRange(nx, ny))
          continue;
        if (m[ny][nx] == '#')
          continue;
        auto result = ac.find(ac_node, dname[d]);
        if (result.second.size() > 0)
          continue;
        ll nnid = result.first->id;
        assert(nnid < n);
        if (dist[y][x][nid] + 1 < dist[ny][nx][nnid]) {
          dist[ny][nx][nnid] = dist[y][x][nid] + 1;
          Q.push({nx, ny, nnid});
        }
      }
    }
    ll ans = linf;
    rep(i, n) chmin(ans, dist[gy][gx][i]);
    if (ans == linf)
      cout << -1 << endl;
    else
      cout << ans << endl;
  }
}

Error: 0

Fixed submission:


#include <algorithm>
#include <assert.h>
#include <bitset>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define rep(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define rep1(i, n) for (int(i) = 1; (i) <= (n); (i)++)
#define FOR(i, a, b) for (int(i) = (a); (i) <= (b); (i)++)
#define db(x)                                                                  \\
  { cout << #x << " = " << (x) << endl; }
#define dba(a, x, y)                                                           \\
  {                                                                            \\
    cout << #a << " :";                                                        \\
    FOR(i123, x, y) cout << setw(4) << (a)[i123];                              \\
    cout << endl;                                                              \\
  }
#define clr(x) memset(x, 0, sizeof(x));
#define mp make_pair
#define pb push_back
#define sz(x) int((x).size())
#define endl '\\n'
#define dx dehejedj
#define dy dehejedjdfejfwjj
typedef long long ll;
typedef long double ld;
const int INF = INT_MAX;
const ll INFL = LLONG_MAX;
const ld pi = acos(-1);
// const int MOD = ;

int N, M;
int numP;
string P[20];
string T[20];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
string URDL = "URDL";
int nxt[105][4];
int bad[105];
int dist[55][55][105];
struct state {
  int x, y, st;
};
int main() {
  while (cin >> N >> M) {
    clr(nxt);
    clr(bad);
    clr(dist);
    if (N == 0 && M == 0)
      return 0;
    rep(i, N) cin >> T[i];
    cin >> numP;
    rep(j, numP) cin >> P[j];
    vector<string> pref;
    rep(j, numP) rep(len, sz(P[j]) + 1) pref.pb(P[j].substr(0, len));
    pref.pb("");
    sort(pref.begin(), pref.end());
    pref.erase(unique(pref.begin(), pref.end()), pref.end());
    rep(i, sz(pref)) {
      rep(j, numP) {
        if (sz(P[j]) <= sz(pref[i]) &&
            pref[i].substr(sz(pref[i]) - sz(P[j])) == P[j]) {
          bad[i] = 1;
        }
      }
      rep(j, 4) {
        string prefplus = pref[i] + URDL[j];
        while (true) {
          int k = (int)(lower_bound(pref.begin(), pref.end(), prefplus) -
                        pref.begin());
          if (k < sz(pref) && pref[k] == prefplus) {
            nxt[i][j] = k;
            break;
          }
          if (sz(prefplus) == 0)
            break;
          prefplus = prefplus.substr(1);
        }
      }
    }
    rep(i, N) rep(j, M) rep(k, sz(pref)) dist[i][j][k] = INF;
    queue<state> q;
    rep(i, N) rep(j, M) if (T[i][j] == 'S') {
      q.push((state){i, j, 0});
      dist[i][j][0] = 0;
    }
    int ans = INF;
    while (!q.empty()) {
      int i = q.front().x;
      int j = q.front().y;
      int st = q.front().st;
      //      cout << "(" << i << ", " << j << ")" << endl;
      //      cout << pref[st] << endl << endl;
      q.pop();
      rep(diri, 4) {
        int ii = i + dx[diri];
        int jj = j + dy[diri];
        if (ii < 0 || N <= ii || jj < 0 || M <= jj)
          continue;
        if (T[ii][jj] == '#')
          continue;
        int nxtst = nxt[st][diri];
        if (bad[nxtst])
          continue;
        if (dist[ii][jj][nxtst] < INF)
          continue;
        dist[ii][jj][nxtst] = dist[i][j][st] + 1;
        if (T[ii][jj] == 'G')
          ans = min(ans, dist[ii][jj][nxtst]);
        q.push((state){ii, jj, nxtst});
      }
    }
    if (ans == INF)
      ans = -1;
    cout << ans << endl;
  }
}