#pragma comment(linker, "/STACK:512000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
#include <bits/stdc++.h>
#ifdef AIM
#include <sys/resource.h>
#endif
using namespace std;

#define all(a) a.begin(), a.end()
typedef long long li;
typedef long double ld;
void solve(__attribute__((unused)) bool);
void precalc();
clock_t start;
#define FILENAME ""

int main() {
#ifdef AIM
  string s = FILENAME;
//    assert(!s.empty());
  //freopen("/home/alexandero/ClionProjects/cryptozoology/input.txt", "r", stdin);
  //freopen("/home/alexandero/ClionProjects/cryptozoology/output.txt", "w", stdout);
#else
//    freopen(FILENAME ".in", "r", stdin);
//    freopen(FILENAME ".out", "w", stdout);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    start = clock();
    int t = 1;
#ifndef AIM
  cout.sync_with_stdio(0);
  cin.tie(0);
#endif

#ifdef AIM
  const rlim_t kStackSize = 256 * 1024 * 1024;
  struct rlimit rl;
  int result;

  result = getrlimit(RLIMIT_STACK, &rl);
  if (result == 0)
  {
    if (rl.rlim_cur < kStackSize)
    {
      rl.rlim_cur = kStackSize;
      result = setrlimit(RLIMIT_STACK, &rl);
      if (result != 0)
      {
        fprintf(stderr, "setrlimit returned result = %d\n", result);
      }
    }
  }
#endif

  precalc();
  cout.precision(10);
  cout << fixed;
  //cin >> t;
  int testNum = 1;
  while (t--) {
      //cout << "Case #" << testNum++ << ": ";
      solve(true);
  }
  cout.flush();
#ifdef AIM
    while (true) {
      solve(false);
  }
#endif

#ifdef AIM
  cout.flush();
  auto end = clock();

  usleep(10000);
  print_stats(end - start);
  usleep(10000);
#endif

    return 0;
}

template<typename T>
T binpow(T q, T w, T mod) {
    if (!w)
        return 1 % mod;
    if (w & 1)
        return q * 1LL * binpow(q, w - 1, mod) % mod;
    return binpow(q * 1LL * q % mod, w / 2, mod);
}

template<typename T>
T gcd(T q, T w) {
    while (w) {
        q %= w;
        swap(q, w);
    }
    return q;
}
template<typename T>
T lcm(T q, T w) {
    return q / gcd(q, w) * w;
}

template <typename T>
void make_unique(vector<T>& a) {
    sort(all(a));
    a.erase(unique(all(a)), a.end());
}

template<typename T>
void relax_min(T& cur, T val) {
    cur = min(cur, val);
}

template<typename T>
void relax_max(T& cur, T val) {
    cur = max(cur, val);
}

void precalc() {
}

//#define int li
//const int mod = 1000000007;

bool local = false;

string pattern = "Atcod3rIsGreat";
const int INF = (int)1e9;

int get_distance(string a, string b) {
  vector<vector<int>> dp(a.size() + 1, vector<int>(b.size() + 1, INF));
  dp[0][0] = 0;
  for (int i = 0; i <= a.size(); ++i) {
    for (int j = 0; j <= b.size(); ++j) {
      if (i + 1 <= a.size()) {
        relax_min(dp[i + 1][j], dp[i][j] + 1);
      }
      if (j + 1 <= b.size()) {
        relax_min(dp[i][j + 1], dp[i][j] + 1);
      }
      if (i < a.size() && j < b.size()) {
        relax_min(dp[i + 1][j + 1], dp[i][j] + (a[i] != b[j]));
      }
    }
  }
  return dp[a.size()][b.size()];
}

int n_queries = 0;

int query(string a) {
  ++n_queries;
  if (local) {
    return get_distance(a, pattern);
  } else {
    cout << "? " << a << endl;
    int res;
    cin >> res;
    return res;
  }
}

#define data sdgasdgfs

vector<pair<string, int>> data;

pair<string, int> get_rec(int l, int r) {
  if (l + 1 == r) {
    return data[l];
  }
  int m = (l + r) / 2;
  auto a_item = get_rec(l, m);
  auto a = a_item.first;
  auto prev_dist = a_item.second;
  auto b = get_rec(m, r).first;
  //cout << a << " " << b << endl;
  reverse(all(b));
  int uk = (int)a.size();
  for (char c : b) {
    while (true) {
      if (uk < 0) {
        a.insert(a.begin(), c);
        --prev_dist;
        break;
      }
      auto candy = a;
      candy.insert(candy.begin() + uk, c);
      auto new_dist = query(candy);
      if (new_dist < prev_dist) {
        prev_dist = new_dist;
        a = candy;
        break;
      }
      --uk;
    }
  }
  return {a, prev_dist};
}

void solve(__attribute__((unused)) bool read) {
  string alphabet;
  for (char c = 'a'; c <= 'z'; ++c) {
    alphabet += c;
  }
  for (char c = 'A'; c <= 'Z'; ++c) {
    alphabet += c;
  }
  for (char c = '0'; c <= '9'; ++c) {
    alphabet += c;
  }

  if (local) {
    pattern.clear();
    for (int i = 0; i < 128; ++i) {
      pattern += alphabet[rand() % alphabet.size()];
    }
  }

  n_queries = 0;
  int L = 0, R = 128;
  while (L + 1 < R) {
    int M = (L + R) / 2;
    if (query(string(M + 1, 'a')) > query(string(M, 'a'))) {
      R = M;
    } else {
      L = M;
    }
  }
  int len = R;
  if (local) {
    assert(len == pattern.length());
  }

  //cerr << "n_queries_before: " << n_queries << endl;

  data.clear();
  for (char c : alphabet) {
    int dist = query(string(len, c));
    if (dist < len) {
      data.push_back({string(len - dist, c), dist});
    }
  }
  string res = get_rec(0, data.size()).first;
  cout << "! " << res << endl;
  if (local) {
    assert(res == pattern);
    cerr << "n_queries: " << n_queries << endl;
    assert(n_queries <= 850);
  }

}

Measured memory_bytes: 3748