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

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <set>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

typedef unsigned long long ULL;

int main() {

  ios::sync_with_stdio(false);
  string s;

  while (cin >> s, s != "#") {

    // 各文字が置換されたものか，そうでないのかを
    // 全パターン試すと各ケースでO(2^n),n<=20であり，
    // ICPCルールなら十分であるが，AOJだとTLE

    // 半分全列挙
    // 前半ss1,n,N 後半ss2,m,M
    // 前半と後半を結合すると結局O(2^n)になるが，
    // 全列挙よりは多少はマシになるはず(?)
    set<string> ss1, ss2;
    int n = s.size() / 2;
    int m = s.size() - n;
    ULL N = (1ULL << n);
    ULL M = (1ULL << m);

    vector<string> ans;

    // 前半
    for (ULL state = 0; state < N; ++state) {
      string str = s.substr(0, n);
      for (int i = 0; i < n; ++i) {
        if ((1 << i) & state && str[i] != 'z')
          str[i]++;
      }

      ss1.insert(str);
    }

    // 後半
    for (ULL state = 0; state < M; ++state) {
      string str = s.substr(n);
      for (char i = 0; i < m; ++i) {
        if ((1 << i) & state && str[i] != 'z')
          str[i]++;
      }

      ss2.insert(str);
    }

    // 前半と後半の結合
    for (auto it1 = ss1.begin(); it1 != ss1.end(); ++it1) {
      for (auto it2 = ss2.begin(); it2 != ss2.end(); it2++) {

        // 再度置換して，入力と同じになればansへ
        string str = (*it1) + (*it2);
        bool app[26] = {false};
        for (char i = 0; i < n + m; ++i) {
          char c = str[i] - 'a';
          if (!app[c] && c != 0) {
            --str[i];
            app[c] = true;
          }
        }
        if (str == s)
          ans.push_back((*it1) + (*it2) + "\\n");
      }
    }

    const ULL sz = ans.size();
    cout << sz << endl;

    if (sz <= 10) {
      for (char i = 0; i < sz; i++)
        cout << ans[i];
    } else {
      cout << ans[0] + ans[1] + ans[2] + ans[3] + ans[4] + ans[sz - 5] +
                  ans[sz - 4] + ans[sz - 3] + ans[sz - 2]
           << ans[sz - 1];
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <set>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

#define MP make_pair
typedef unsigned long long ULL;

/*
string enc(string s){

        bool app[26];
        for(int i=0;i<26;i++) app[i]=false;

        string str=s;
        for(int i=0;i<s.size();i++){
                char c=s[i]-'a';
                if(!app[c] && c!=0){
                        str[i]--;
                        app[c]=true;
                }
        }

        return str;

}
*/

int main() {

  string s;
  while (cin >> s, s != "#") {

    set<string> ans;
    const int n = s.size();
    const ULL N = (1 << s.size());

    for (ULL state = 1; state < N; state++) {
      string str = s;
      ULL tmp = state;
      for (int i = 0; i < n; i++) {
        if (tmp % 2 && str[i] != 'z')
          str[i]++;
        tmp /= 2;
      }

      bool app[26] = {false};
      string es = str;

      for (int i = 0; i < es.size(); i++) {
        char c = es[i] - 'a';
        if (!app[c] && c != 0) {
          es[i]--;
          app[c] = true;
        }
      }

      if (es == s)
        ans.insert(str);
    }

    const ULL M = ans.size();
    cout << M << endl;

    if (M <= 10) {
      for (auto it = ans.begin(); it != ans.end(); it++)
        printf("%s\\n", (*it).c_str());
    } else {
      int i = 0;
      for (auto it = ans.begin(); i < 5; it++, i++)
        printf("%s\\n", (*it).c_str());

      auto it = ans.end();
      for (i = 0; i < 5; i++)
        it--;
      for (i = 0; i < 5; i++)
        printf("%s\\n", (*(it++)).c_str());
    }
  }

  return 0;
}