//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#ifndef LOCAL
#pragma GCC optimize("O3")
#endif
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define st first
#define nd second

using namespace __gnu_pbds;
using namespace std;
 
template <typename T>
using ordered_set =
	tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
 
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
 
#define shandom_ruffle random_shuffle
 
using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;

string alpha;
int slen;

map<string, int> memo;

string hidden;
int nqueries = 0;
vi counts;

int Ask(string s) {
	if (memo.count(s)) { debug() << imie(s); return memo[s]; }
	//~ debug() << imie(s);
	++nqueries;
	if (nqueries > 850) {
		int x = *max_element(ALL(counts));
		int *y = new int[x * 5000 * 1000];
		for (int i = 0; i < x * 5000 * 1000; ++i) {
			y[i] = 4;
		}
		assert(false);
	}
	#ifdef LOCAL
	int A = SZ(hidden);
	int B = SZ(s);
	vector<vi> dp(A + 1, vi(B + 1));
	for (int i = 0; i <= B; ++i) { dp[0][i] = i; }
	for (int j = 1; j <= A; ++j) {
		dp[j][0] = j;
		for (int i = 1; i <= B; ++i) {
			dp[j][i] = min({dp[j][i-1], dp[j-1][i], dp[j-1][i-1]}) + 1;
			if (hidden[j-1] == s[i-1]) {
				dp[j][i] = min(dp[j][i], dp[j-1][i-1]);
			}
		}
	}
	int ans = dp.back().back();
	//~ debug() << imie(hidden) << imie(s) << imie(ans);
	return memo[s] = ans;
	#else
	cout << "? " << s << endl;
	int ans;
	cin >> ans;
	return memo[s] = ans;
	#endif
}

bool IsSubstr(string s) {
	return Ask(s) + SZ(s) == slen;
}

vector<string> merges;

void SortMerges() {
	sort(ALL(merges), [&](const string &lhs, const string &rhs) {
		return SZ(lhs) > SZ(rhs);
	});
}

int main() {
	#ifdef LOCAL
	cin >> hidden;
	#endif
	
	for (char ch = '0'; ch <= '9'; ++ch) { alpha += ch; }
	for (char ch = 'A'; ch <= 'Z'; ++ch) { alpha += ch; }
	for (char ch = 'a'; ch <= 'z'; ++ch) { alpha += ch; }
	cerr << alpha << "\n";

	const int A = SZ(alpha);

	vi ehh(A);
	for (int i = 0; i < A; ++i) {
		ehh[i] = Ask(string(2, alpha[i]));
	}

	int who_min = min_element(ALL(ehh)) - ehh.begin();
	int mindist = ehh[who_min];
	slen = mindist + 2;
	int pair_threshold = mindist;
	int dddd = Ask(string(1, alpha[who_min]));
	if (dddd == 0) {
		cout << "! " << alpha[who_min] << "\n";
		return 0;
	}
	if (dddd != slen - 1) {
		--slen;
		--pair_threshold;
	}

	debug() << imie(slen) << imie(mindist) << imie(pair_threshold);
	
	counts.resize(A);
	for (int i = 0; i < SZ(alpha); ++i) {
		char ch = alpha[i];
		if (ehh[i] == pair_threshold) {
			for (int len = 2; len <= slen; ++len) {
				if (IsSubstr(string(len, ch))) {
					counts[i] = len;
				} else {
					break;
				}
			}
		} else {
			if (IsSubstr(string(1, ch))) {
				counts[i] = 1;
			}
		}
	}

	for (int i = 0; i < A; ++i) {
		if (!counts[i]) { continue; }
		merges.push_back(string(counts[i], alpha[i]));
	}

	debug() << imie(merges);
	int maxqueries = nqueries;
	int incq = 0;
	cerr << nqueries << "\n";

	while (SZ(merges) > 1) {
		SortMerges();
		string a = merges.back();
		merges.pop_back();
		string b = merges.back();
		merges.pop_back();

		incq += SZ(a) + SZ(b) - 1;
		maxqueries += SZ(a) + SZ(b) - 1;

		//~ assert(maxqueries <= 850);

		string suf_a = a;
		string merged;
		for (char ch : b) {
			while (true) {
				if (suf_a.empty()) { break; }
				if (IsSubstr(merged + ch + suf_a)) {
					break;
				} else {
					assert(!suf_a.empty());
					merged += suf_a[0];
					suf_a.erase(suf_a.begin());
				}
			}
			merged += ch;
		}
		merged += suf_a;

		debug() << imie(a) << imie(b) << imie(merged) << imie(incq);
		merges.push_back(merged);
	}

	#ifdef LOCAL
	assert(Ask(merges[0]) == 0);
	#endif
	cout << "! " << merges[0] << endl;
	cerr << maxqueries << " " << incq << "\n";
	cerr << nqueries << "\n";
}


Measured memory_bytes: 3800