Problem p00896 (C++)

Buggy submission (status: Runtime Error):
#pragma GCC optimize "O3"

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 20;

int n, ans;
string tmp, ans_rev;
vector<string> words[N + 1], cands[N + 1];
// vector<bool> vis[N+1];

void init() {
  for (int i = 0; i <= N; ++i)
    words[i].clear(), cands[i].clear(); //, vis[i].clear();
  ans = 0;
}
bool valid(const string &tar, const string &s, string &rev) {
  assert(s.size() == tar.size());
  for (size_t i = 0; i < s.size(); ++i) {
    if (rev[s[i]] != -1 && rev[s[i]] != tar[i])
      return false;
    if (rev[tar[i]] != -1 && rev[tar[i]] != s[i])
      return false;
    if (rev[s[i]] == -1 && rev[tar[i]] != -1)
      return false;
    if (rev[tar[i]] == -1 && rev[s[i]] != -1)
      return false;
  }
  return true;
}
void dfs(int l, size_t x, string rev) {
  if (ans > 1)
    return;
  while (l && x >= words[l].size()) {
    x = 0;
    --l;
  }
  if (l == 0) {
    ans_rev = rev;
    ++ans;
    return;
  }
  const string &tar = words[l][x];
  for (size_t j = 0; j < cands[l].size(); ++j) {
    // if(vis[l][j])
    //   continue;
    const string &s = cands[l][j];
    if (valid(tar, s, rev)) {
      string nrev = rev;
      for (size_t i = 0; i < s.size(); ++i) {
        nrev[s[i]] = tar[i];
        nrev[tar[i]] = s[i];
      }
      // vis[l][j] = true;
      dfs(l, x + 1, nrev);
      // vis[l][j] = false;
    }
  }
}
void cleanup(vector<string> &v) {
  sort(v.begin(), v.end());
  v.erase(unique(v.begin(), v.end()));
}
void solve() {
  init();
  for (int i = 0; i < n; ++i) {
    cin >> tmp;
    for_each(tmp.begin(), tmp.end(), [](char &c) { c -= 'A'; });
    cands[tmp.size()].push_back(tmp);
  }
  // for(int i = 0; i<=N; ++i)
  //   vis[i].resize(cands[i].size());
  vector<string> sent;
  bool cont = true;
  while (cont) {
    cin >> tmp;
    if (tmp.back() == '.') {
      tmp.pop_back();
      cont = false;
    }
    sent.push_back(tmp);
    for_each(tmp.begin(), tmp.end(), [](char &c) { c -= 'A'; });
    words[tmp.size()].push_back(tmp);
  }
  for (int i = 0; i <= N; ++i)
    cleanup(words[i]);
  dfs(N, 0, string(26, -1));
  assert(ans > 0);
  if (ans == 1) {
    for (auto c : ans_rev)
      if (c != -1) {
        assert(c == ans_rev[ans_rev[c]]);
      }
    for (size_t i = 0; i < sent.size(); ++i) {
      for (auto c : sent[i])
        putchar(ans_rev[c - 'A'] == -1 ? c : ans_rev[c - 'A'] + 'A');
      putchar(i + 1 == sent.size() ? '.' : ' ');
    }
    puts("");
  } else
    puts("-.");
}
int main() {
  while (scanf("%d", &n) == 1 && n)
    solve();
}

Fixed submission:
#pragma GCC optimize "O3"

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 20;

int n, ans;
string tmp, ans_rev;
vector<string> words[N + 1], cands[N + 1];
// vector<bool> vis[N+1];

void init() {
  for (int i = 0; i <= N; ++i)
    words[i].clear(), cands[i].clear(); //, vis[i].clear();
  ans = 0;
}
bool valid(const string &tar, const string &s, string &rev) {
  assert(s.size() == tar.size());
  for (size_t i = 0; i < s.size(); ++i) {
    if (rev[s[i]] != -1 && rev[s[i]] != tar[i])
      return false;
    if (rev[tar[i]] != -1 && rev[tar[i]] != s[i])
      return false;
    if (rev[s[i]] == -1 && rev[tar[i]] != -1)
      return false;
    if (rev[tar[i]] == -1 && rev[s[i]] != -1)
      return false;
  }
  return true;
}
void dfs(int l, size_t x, string rev) {
  if (ans > 1)
    return;
  while (l && x >= words[l].size()) {
    x = 0;
    --l;
  }
  if (l == 0) {
    ans_rev = rev;
    ++ans;
    return;
  }
  const string &tar = words[l][x];
  for (size_t j = 0; j < cands[l].size(); ++j) {
    // if(vis[l][j])
    //   continue;
    const string &s = cands[l][j];
    if (valid(tar, s, rev)) {
      string nrev = rev;
      for (size_t i = 0; i < s.size(); ++i) {
        nrev[s[i]] = tar[i];
        nrev[tar[i]] = s[i];
      }
      // vis[l][j] = true;
      dfs(l, x + 1, nrev);
      // vis[l][j] = false;
    }
  }
}
void cleanup(vector<string> &v) {
  sort(v.begin(), v.end());
  v.resize(unique(v.begin(), v.end()) - v.begin());
}
void solve() {
  init();
  for (int i = 0; i < n; ++i) {
    cin >> tmp;
    for_each(tmp.begin(), tmp.end(), [](char &c) { c -= 'A'; });
    cands[tmp.size()].push_back(tmp);
  }
  // for(int i = 0; i<=N; ++i)
  //   vis[i].resize(cands[i].size());
  vector<string> sent;
  bool cont = true;
  while (cont) {
    cin >> tmp;
    if (tmp.back() == '.') {
      tmp.pop_back();
      cont = false;
    }
    sent.push_back(tmp);
    for_each(tmp.begin(), tmp.end(), [](char &c) { c -= 'A'; });
    words[tmp.size()].push_back(tmp);
  }
  for (int i = 0; i <= N; ++i)
    cleanup(words[i]);
  dfs(N, 0, string(26, -1));
  assert(ans > 0);
  if (ans == 1) {
    for (auto c : ans_rev)
      if (c != -1) {
        assert(c == ans_rev[ans_rev[c]]);
      }
    for (size_t i = 0; i < sent.size(); ++i) {
      for (auto c : sent[i])
        putchar(ans_rev[c - 'A'] == -1 ? c : ans_rev[c - 'A'] + 'A');
      putchar(i + 1 == sent.size() ? '.' : ' ');
    }
    puts("");
  } else
    puts("-.");
}
int main() {
  while (scanf("%d", &n) == 1 && n)
    solve();
}