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

#include <algorithm>
#include <bitset>
#include <iostream>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

class Matcher {
  struct PMA {
    int next[256];
    vector<int> accept;
    PMA() { fill(next, next + 256, -1); }
  };
  vector<PMA> states;

public:
  Matcher(const vector<string> &patterns) {
    states.push_back(PMA());
    for (int i = 0; i < patterns.size(); ++i) {
      int cur = 0;
      for (size_t j = 0; j < patterns[i].size(); ++j) {
        char c = patterns[i][j];
        if (states[cur].next[c] < 0) {
          states[cur].next[c] = static_cast<int>(states.size());
          states.push_back(PMA());
        }
        cur = states[cur].next[c];
      }
      states[cur].accept.push_back(i);
    }
    queue<int> q;
    for (int c = 1; c < 256; ++c) {
      if (states[0].next[c] >= 0) {
        states[states[0].next[c]].next[0] = 0;
        q.push(states[0].next[c]);
      } else {
        states[0].next[c] = 0;
      }
    }
    while (!q.empty()) {
      int t = q.front();
      q.pop();
      for (int c = 1; c < 256; ++c) {
        if (states[t].next[c] >= 0) {
          q.push(states[t].next[c]);
          int r = states[t].next[0];
          while (states[r].next[c] < 0) {
            r = states[r].next[0];
          }
          states[states[t].next[c]].next[0] = states[r].next[c];
        }
      }
    }
    for (int i = 0; i < patterns.size(); ++i) {
      const string &pat = patterns[i];
      for (int j = 1; j < states.size(); ++j) {
        int current = j, k = 0;
        for (; k < pat.size(); ++k) {
          if (states[current].next[pat[k]] < 0) {
            break;
          }
          current = states[current].next[pat[k]];
        }
        if (k == pat.size()) {
          states[current].accept.push_back(i);
        }
      }
    }
  }
  int match(char c, int &result, int state = 0) {
    while (states[state].next[c] < 0) {
      state = states[state].next[0];
    }
    state = states[state].next[c];
    for (size_t j = 0; j < states[state].accept.size(); ++j) {
      result = states[state].accept[j];
    }
    return state;
  }
  int stateNum() const { return static_cast<int>(states.size()); }
};

const int BASE64_TABLE[] = {
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  62, 0,  0,  0,  63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
    61, 0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,  0,  0,  0,
    0,  0,  26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
    43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  0,  0,  0,  0,
};

string base64decode(string s, int length) {
  stringstream ss;
  for (int i = 0; i < s.size(); ++i) {
    int x = BASE64_TABLE[s[i]];
    for (int j = 5; j >= 0; --j) {
      ss << ((x >> j) & 1);
    }
  }
  return ss.str().substr(0, length);
}

int main() {
  while (true) {
    int w, h, p;
    cin >> w >> h >> p;
    if (w == 0 && h == 0 && p == 0) {
      break;
    }
    vector<string> image(h);
    for (int i = 0; i < h; ++i) {
      string enc;
      cin >> enc;
      image[i] = base64decode(enc, w);
    }
    vector<string> pattern(p);
    for (int i = 0; i < p; ++i) {
      string enc;
      cin >> enc;
      pattern[i] = base64decode(enc, p);
    }
    int answer = 0;
    set<vector<string>> checked;
    vector<string> table(w, string(h, '\\x7f'));
    vector<string> next(p, string(p, ' '));
    for (int r = 0; r < 8; ++r) {
      if (checked.find(pattern) == checked.end()) {
        checked.insert(pattern);
        vector<string> gpat;
        string goal;
        for (int i = 0; i < p; ++i) {
          vector<string>::iterator it =
              find(gpat.begin(), gpat.end(), pattern[i]);
          if (it == gpat.end()) {
            gpat.push_back(pattern[i]);
            goal += static_cast<char>(gpat.size());
          } else {
            goal += static_cast<char>(distance(gpat.begin(), it) + 1);
          }
        }
        Matcher firstMatcher(gpat);
        for (int i = 0; i < h; ++i) {
          int state = 0;
          for (int j = 0; j < w; ++j) {
            int result = -2;
            state = firstMatcher.match(image[i][j], result, state);
            table[j][i] = static_cast<char>((result + 1) & 0x7f);
          }
        }
        Matcher secondMatcher(vector<string>(1, goal));
        for (int i = 0; i < w; ++i) {
          int state = 0;
          for (int j = 0; j < h; ++j) {
            int result = -1;
            state = secondMatcher.match(table[i][j], result, state);
            answer += result + 1;
          }
        }
      }
      for (int i = 0; i < p; ++i) {
        for (int j = 0; j < p; ++j) {
          next[i][j] = pattern[j][p - i - 1];
        }
      }
      pattern.swap(next);
      if (r == 3) {
        for (int i = 0; i < p; ++i) {
          reverse(pattern[i].begin(), pattern[i].end());
        }
      }
    }
    cout << answer << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <bitset>
#include <iostream>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

class Matcher {
  struct PMA {
    int next[256];
    vector<int> accept;
    PMA() { fill(next, next + 256, -1); }
  };
  vector<PMA> states;

public:
  Matcher(const vector<string> &patterns) {
    states.push_back(PMA());
    for (int i = 0; i < patterns.size(); ++i) {
      int cur = 0;
      for (size_t j = 0; j < patterns[i].size(); ++j) {
        char c = patterns[i][j];
        if (states[cur].next[c] < 0) {
          states[cur].next[c] = static_cast<int>(states.size());
          states.push_back(PMA());
        }
        cur = states[cur].next[c];
      }
      states[cur].accept.push_back(i);
    }
    queue<int> q;
    for (int c = 1; c < 256; ++c) {
      if (states[0].next[c] >= 0) {
        states[states[0].next[c]].next[0] = 0;
        q.push(states[0].next[c]);
      } else {
        states[0].next[c] = 0;
      }
    }
    while (!q.empty()) {
      int t = q.front();
      q.pop();
      for (int c = 1; c < 256; ++c) {
        if (states[t].next[c] >= 0) {
          q.push(states[t].next[c]);
          int r = states[t].next[0];
          while (states[r].next[c] < 0) {
            r = states[r].next[0];
          }
          states[states[t].next[c]].next[0] = states[r].next[c];
        }
      }
    }
    for (int i = 0; i < patterns.size(); ++i) {
      const string &pat = patterns[i];
      for (int j = 1; j < states.size(); ++j) {
        int current = j, k = 0;
        for (; k < pat.size(); ++k) {
          if (states[current].next[pat[k]] < 0) {
            break;
          }
          current = states[current].next[pat[k]];
        }
        if (k == pat.size()) {
          states[current].accept.push_back(i);
        }
      }
    }
  }
  int match(char c, int &result, int state = 0) {
    while (states[state].next[c] < 0) {
      state = states[state].next[0];
    }
    state = states[state].next[c];
    for (size_t j = 0; j < states[state].accept.size(); ++j) {
      result = states[state].accept[j];
    }
    return state;
  }
  int stateNum() const { return static_cast<int>(states.size()); }
};

const int BASE64_TABLE[] = {
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  62, 0,  0,  0,  63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
    61, 0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,  0,  0,  0,
    0,  0,  26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
    43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  0,  0,  0,  0,
};

string base64decode(string s, int length) {
  stringstream ss;
  for (int i = 0; i < s.size(); ++i) {
    int x = BASE64_TABLE[s[i]];
    for (int j = 5; j >= 0; --j) {
      ss << ((x >> j) & 1);
    }
  }
  return ss.str().substr(0, length);
}

int main() {
  while (true) {
    int w, h, p;
    cin >> w >> h >> p;
    if (w == 0 && h == 0 && p == 0) {
      break;
    }
    vector<string> image(h);
    for (int i = 0; i < h; ++i) {
      string enc;
      cin >> enc;
      image[i] = base64decode(enc, w);
    }
    vector<string> pattern(p);
    for (int i = 0; i < p; ++i) {
      string enc;
      cin >> enc;
      pattern[i] = base64decode(enc, p);
    }
    int answer = 0;
    set<vector<string>> checked;
    vector<string> table(w, string(h, '\\xff'));
    vector<string> next(p, string(p, ' '));
    for (int r = 0; r < 8; ++r) {
      if (checked.find(pattern) == checked.end()) {
        checked.insert(pattern);
        vector<string> gpat;
        string goal;
        for (int i = 0; i < p; ++i) {
          vector<string>::iterator it =
              find(gpat.begin(), gpat.end(), pattern[i]);
          if (it == gpat.end()) {
            gpat.push_back(pattern[i]);
            goal += static_cast<char>(gpat.size());
          } else {
            goal += static_cast<char>(distance(gpat.begin(), it) + 1);
          }
        }
        Matcher firstMatcher(gpat);
        for (int i = 0; i < h; ++i) {
          int state = 0;
          for (int j = 0; j < w; ++j) {
            int result = -2;
            state = firstMatcher.match(image[i][j], result, state);
            table[j][i] = static_cast<char>(result + 1);
          }
        }
        Matcher secondMatcher(vector<string>(1, goal));
        for (int i = 0; i < w; ++i) {
          int state = 0;
          for (int j = 0; j < h; ++j) {
            int result = -1;
            state = secondMatcher.match(table[i][j], result, state);
            answer += result + 1;
          }
        }
      }
      for (int i = 0; i < p; ++i) {
        for (int j = 0; j < p; ++j) {
          next[i][j] = pattern[j][p - i - 1];
        }
      }
      pattern.swap(next);
      if (r == 3) {
        for (int i = 0; i < p; ++i) {
          reverse(pattern[i].begin(), pattern[i].end());
        }
      }
    }
    cout << answer << endl;
  }
  return 0;
}