// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <class C>
constexpr auto ssize(const C& c)
    -> std::common_type_t<std::ptrdiff_t,
                          std::make_signed_t<decltype(c.size())>> {
  return (std::common_type_t<std::ptrdiff_t,
                             std::make_signed_t<decltype(c.size())>>)c.size();
}

template <class T, std::ptrdiff_t N>
constexpr std::ptrdiff_t ssize(const T (&)[N]) noexcept {
  return N;
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, bool> has_single_bit(
    T x) noexcept {
  return x != 0 && (x & (x - 1)) == 0;
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, int> countl_zero(
    T x) noexcept {
  if constexpr (sizeof(T) <= sizeof(unsigned)) {
    return __builtin_clz(x) - (std::numeric_limits<unsigned>::digits -
                               std::numeric_limits<T>::digits);
  } else if constexpr (sizeof(T) <= sizeof(unsigned long)) {
    return __builtin_clzl(x) - (std::numeric_limits<unsigned long>::digits -
                                std::numeric_limits<T>::digits);
  } else {
    static_assert(sizeof(T) <= sizeof(unsigned long long));
    return __builtin_clzll(x) -
           (std::numeric_limits<unsigned long long>::digits -
            std::numeric_limits<T>::digits);
  }
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, int> countr_zero(
    T x) noexcept {
  if constexpr (sizeof(T) <= sizeof(unsigned)) {
    return __builtin_ctz(x);
  } else if constexpr (sizeof(T) <= sizeof(unsigned long)) {
    return __builtin_ctzl(x);
  } else {
    static_assert(sizeof(T) <= sizeof(unsigned long long));
    return __builtin_ctzll(x);
  }
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, int> popcount(T x) noexcept {
  if constexpr (sizeof(T) <= sizeof(unsigned)) {
    return __builtin_popcount(x);
  } else if constexpr (sizeof(T) <= sizeof(unsigned long long)) {
    return __builtin_popcountl(x);
  } else {
    static_assert(sizeof(T) <= sizeof(unsigned long long));
    return __builtin_popcountll(x);
  }
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, T> bit_width(T x) noexcept {
  return (T)(std::numeric_limits<T>::digits - countl_zero(x));
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, T> bit_ceil(T x) noexcept {
  return (T)(x <= 1 ? 1 : (T)1 << bit_width((T)(x - 1)));
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, T> bit_floor(T x) noexcept {
  return (T)(x == 0 ? 0 : (T)1 << (bit_width(x) - 1));
}

template <class Fun>
class y_combinator_result {
 public:
  template <class T>
  explicit y_combinator_result(T&& fun) : fun_(std::forward<T>(fun)) {}

  template <class... Args>
  decltype(auto) operator()(Args&&... args) {
    return fun_(std::ref(*this), std::forward<Args>(args)...);
  }

 private:
  Fun fun_;
};

template <class Fun>
decltype(auto) y_combinator(Fun&& fun) {
  return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::optional<T>& opt) {
  return opt ? os << *opt : os << "nullopt";
}

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <typename Container,
          std::enable_if_t<!std::is_convertible_v<Container, std::string_view>,
                           typename Container::const_iterator>* = nullptr>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

template <typename T, typename Container>
std::ostream& operator<<(std::ostream& os, std::stack<T, Container> s) {
  std::vector<T> v(s.size());
  for (auto it = v.rbegin(); it != v.rend(); ++it) {
    *it = s.top();
    s.pop();
  }
  return os << v;
}

template <typename T, typename Container>
std::ostream& operator<<(std::ostream& os, std::queue<T, Container> q) {
  os << '{';
  if (!q.empty()) {
    os << q.front();
    q.pop();
    while (!q.empty()) {
      os << ", " << q.front();
      q.pop();
    }
  }
  return os << '}';
}

template <typename T, typename Container, typename Compare>
std::ostream& operator<<(std::ostream& os,
                         std::priority_queue<T, Container, Compare> pq) {
  os << '{';
  if (!pq.empty()) {
    os << pq.top();
    pq.pop();
    while (!pq.empty()) {
      os << ", " << pq.top();
      pq.pop();
    }
  }
  return os << '}';
}

namespace detail {

template <int I, typename... Ts>
void tuple_print(std::ostream& os, const std::tuple<Ts...>& t) {
  static_assert(0 <= I && I <= sizeof...(Ts));
  if constexpr (I != sizeof...(Ts)) {
    if constexpr (I != 0) {
      os << ", ";
    }
    os << std::get<I>(t);
    tuple_print<I + 1>(os, t);
  }
}

}  // namespace detail

template <typename... Ts>
std::ostream& operator<<(std::ostream& os, const std::tuple<Ts...>& t) {
  os << '{';
  detail::tuple_print<0>(os, t);
  return os << '}';
}

namespace detail {

template <typename T1, typename... Ts>
void debug_print(std::string_view keys, const T1& val1, const Ts&... vals) {
  if constexpr (sizeof...(Ts) == 0) {
    std::cerr << keys << " = " << val1 << std::endl;
  } else {
    for (int i = 0, paren = 0; i < (int)keys.size(); ++i) {
      if (keys[i] == '(' || keys[i] == '{') {
        ++paren;
      } else if (keys[i] == ')' || keys[i] == '}') {
        --paren;
      } else if (keys[i] == ',' && paren == 0) {
        std::cerr << keys.substr(0, i) << " = " << val1 << ',';
        return debug_print(keys.substr(i + 1), vals...);
      }
    }
  }
}

template <typename... Ts>
void debug_print(int line, const Ts&... keyvals) {
  if constexpr (sizeof...(Ts) <= 1) {
    std::cerr << "  " << line << " |" << std::endl;
  } else {
    std::cerr << "  " << line << " | ";
    debug_print(keyvals...);
  }
}

}  // namespace detail

#if defined(TYLER) && defined(__GNUC__) && __GNUC__ >= 8
#define debug(...) \
  detail::debug_print(__LINE__, #__VA_ARGS__ __VA_OPT__(, ) __VA_ARGS__)
#elif defined(TYLER)
#define debug(...) detail::debug_print(__LINE__, #__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) ((void)0)
#endif

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  std::mt19937 rng((std::uint_fast32_t)std::chrono::high_resolution_clock::now()
                       .time_since_epoch()
                       .count());
  constexpr int L = 128;
  constexpr auto comp = [&](const string& a, const string& b) {
    return a.size() > b.size();
  };
  priority_queue<string, vector<string>, decltype(comp)> pq(comp);
  int cnt = 0;
  auto ask = [&](const string& s) {
    if (++cnt > 850) {
      assert(false);
    }
    cout << "? " << s << endl;
    int dist;
    cin >> dist;
    return dist;
  };
  int len = 0;
  for (auto [start, end] : {pair{'a', 'z'}, {'A', 'Z'}, {'0', '9'}}) {
    for (char c = start; c <= end; ++c) {
      int dist = ask(string(L, c));
      if (L - dist > 0) {
        pq.emplace(L - dist, c);
        len += L - dist;
      }
    }
  }
  while (pq.size() > 1) {
    string a = pq.top();
    pq.pop();
    string b = pq.top();
    pq.pop();
    for (int i = 0; !b.empty(); ++i) {
      a.insert(a.begin() + i, b.front());
      int dist = ask(a);
      if (dist == len - (int)a.size()) {
        b.erase(b.begin());
      } else {
        a.erase(a.begin() + i);
      }
    }
    pq.push(a);
  }
  cout << "! " << pq.top() << endl;
  return 0;
}

// Abandon. I think solution 2 in the editorial is wrong.
int main_wa() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  std::mt19937 rng((std::uint_fast32_t)std::chrono::high_resolution_clock::now()
                       .time_since_epoch()
                       .count());
  constexpr int L = 128;
  int counter = 0;
  auto ask = [&](const string& s) {
    if (++counter > 850) {
      assert(false);
    }
    cout << "? " << s << endl;
    int dist;
    cin >> dist;
    return dist;
  };
  string abc;
  for (auto [start, end] : {pair{'a', 'z'}, {'A', 'Z'}, {'0', '9'}}) {
    for (char c = start; c <= end; ++c) {
      abc += c;
    }
  }
#ifdef TYLER
  abc = "ab";
#endif
  int n = (int)abc.size();
  uniform_int_distribution<int> dis(0, n - 1);
  int len = 0;
  vector<int> cnt;
  for (char c : abc) {
    int dist = ask(string(L, c));
    cnt.push_back(L - dist);
    len += L - dist;
  }
  string ans(len, '?');
  auto solve = y_combinator(
      [&](auto self, int low, int high, const vector<int>& total) -> void {
        debug(low, high, total);
        if (low == high) {
          for (int i = 0; i < n; ++i) {
            if (total[i] == 1) {
              ans[low] = abc[i];
              return;
            }
          }
          assert(false);
        }
        int mid = (low + high) >> 1;
        int n_left = mid - low + 1;
        vector<int> left(n);
        int sum = 0, num = 0;
        int best = dis(rng);
        for (int i = 0; i < n; ++i) {
          if (cnt[i] < cnt[best]) {
            best = i;
          }
        }
        for (int i = 0; i < n; ++i) {
          if (total[i] > 0) {
            string s(len, abc[best]);
            for (int j = low; j <= mid; ++j) {
              s[j] = abc[i];
            }
            left[i] = len - ask(s);
            sum += left[i];
            ++num;
          }
        }
        assert((sum - n_left) % num == 0);
        int base = (sum - n_left) / num;
        vector<int> right(n);
        for (int i = 0; i < n; ++i) {
          if (total[i] > 0) {
            left[i] -= base;
            right[i] = total[i] - left[i];
          }
        }
        self(low, mid, left);
        self(mid + 1, high, right);
      });
  solve(0, len - 1, cnt);
  cout << "! " << ans << endl;
  return 0;
}

Measured memory_bytes: 3784