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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cerr << *i << " ";
  cerr << endl;
}
inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

vector<string> split_sentence(string s) {
  vector<string> res;
  REP(i, s.size()) if (s[i] == '.') s[i] = ' ';
  stringstream ss(s);
  string t;
  while (ss >> t) {
    res.push_back(t);
  }
  return res;
}

bool comp(string s, string t) {
  if (s.size() != t.size())
    return s.size() > t.size();
  return s > t;
}

class DFSError {};

bool answer_exist;
string answer;
int mem[80];
int match[26];
string sentence;
vector<string> words;
vector<string> ciphers;
void dfs(int k) {
  if (k == ciphers.size()) {
    if (answer_exist)
      throw DFSError();
    answer_exist = true;
    answer = sentence;
    REP(i, answer.size())
    if (isupper(answer[i])) answer[i] = match[answer[i] - 'A'] + 'A';
  } else {
    string &cipher = ciphers[k];
    int save_match[26];
    memcpy(save_match, match, sizeof match);
    REP(i, words.size()) if (words[i].size() == cipher.size()) {
      string &word = words[i];

      bool ok = true;
      REP(j, word.size()) {
        int A = word[j] - 'A';
        int B = cipher[j] - 'A';
        if (match[A] == -1 && match[B] == -1) {
          match[A] = B;
          match[B] = A;
        } else if (match[A] == B && match[B] == A) {
        } else {
          // printf("match[%c] = %c, match[%c] = %c\\n", A + 'A', match[A] + 'A',
          // B + 'A', match[B] + 'A');
          ok = false;
          break;
        }
      }

      if (ok) {
        mem[k] = i;
        dfs(k + 1);
      }

      memcpy(match, save_match, sizeof match);
    }
  }
}

int main() {
  int N;
  while (cin >> N && N) {
    words.assign(N, "");
    REP(i, N) cin >> words[i];
    cin.ignore();

    getline(cin, sentence);
    ciphers = split_sentence(sentence);

    sort(words.begin(), words.end());
    words.erase(unique(words.begin(), words.end()), words.end());
    sort(ciphers.begin(), ciphers.end(), comp);
    ciphers.erase(unique(ciphers.begin(), ciphers.end()), ciphers.end());

    try {
      answer_exist = false;
      memset(match, -1, sizeof match);
      dfs(0);
      assert(answer_exist);
      cout << answer << endl;
    } catch (DFSError e) {
      cout << "-." << endl;
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cerr << *i << " ";
  cerr << endl;
}
inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

vector<string> split_sentence(string s) {
  vector<string> res;
  REP(i, s.size()) if (s[i] == '.') s[i] = ' ';
  stringstream ss(s);
  string t;
  while (ss >> t) {
    res.push_back(t);
  }
  return res;
}

bool comp(string s, string t) { return s.size() > t.size(); }

class DFSError {};

bool answer_exist;
string answer;
int mem[80];
int match[26];
string sentence;
vector<string> words;
vector<string> ciphers;
void dfs(int k) {
  if (k == ciphers.size()) {
    if (answer_exist)
      throw DFSError();
    answer_exist = true;
    answer = sentence;
    REP(i, answer.size())
    if (isupper(answer[i])) answer[i] = match[answer[i] - 'A'] + 'A';
  } else {
    string &cipher = ciphers[k];
    int save_match[26];
    memcpy(save_match, match, sizeof match);
    REP(i, words.size()) if (words[i].size() == cipher.size()) {
      string &word = words[i];

      bool ok = true;
      REP(j, word.size()) {
        int A = word[j] - 'A';
        int B = cipher[j] - 'A';
        if (match[A] == -1 && match[B] == -1) {
          match[A] = B;
          match[B] = A;
        } else if (match[A] == B && match[B] == A) {
        } else {
          // printf("match[%c] = %c, match[%c] = %c\\n", A + 'A', match[A] + 'A',
          // B + 'A', match[B] + 'A');
          ok = false;
          break;
        }
      }
      if (ok) {
        mem[k] = i;
        dfs(k + 1);
      }
      memcpy(match, save_match, sizeof match);
    }
  }
}

int main() {
  int N;
  while (cin >> N && N) {
    words.assign(N, "");
    REP(i, N) cin >> words[i];
    cin.ignore();

    getline(cin, sentence);
    ciphers = split_sentence(sentence);

    sort(words.begin(), words.end());
    words.erase(unique(words.begin(), words.end()), words.end());
    sort(ciphers.begin(), ciphers.end(), comp);

    try {
      answer_exist = false;
      memset(match, -1, sizeof match);
      dfs(0);
      assert(answer_exist);
      cout << answer << endl;
    } catch (DFSError e) {
      cout << "-." << endl;
    }
  }
  return 0;
}