#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using ld = long double;

#define mp make_pair

const int p = 17;


int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}


mt19937 rnd(time(0));

struct DSU {
    vector<int> sz;
    vector<int> parent;

    void make_set(int v) {
        parent[v] = v;
        sz[v] = 1;
    }

    int find_set(int v) {
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }

    void union_sets(int a, int b) {
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (sz[a] < sz[b])
                swap(a, b);
            parent[b] = a;
            sz[a] += sz[b];
        }
    }

    DSU(int n) {
        sz.resize(n);
        parent.resize(n);
        for (int i = 0; i < n; i++) make_set(i);
    }
};

/*
const int N = 1200000;

vector<int> facs(N), invfacs(N);

void init()
{
    facs[0] = 1;
    for (int i = 1; i<N; i++) facs[i] = mul(facs[i-1], i);
    invfacs[N-1] = inv(facs[N-1]);
    for (int i = N-2; i>=0; i--) invfacs[i] = mul(invfacs[i+1], i+1);
}

int C(int n, int k)
{
    if (n<k) return 0;
    return mul(facs[n], mul(invfacs[k], invfacs[n-k]));
}
*/

/*

pair<int, int> solve1(ll l, ll r)
{
    int answer = 0;
    while (l>= answer+1 || r>=answer+1)
    {
        answer++;
        if (l>=r) l-=answer; else r-=answer;
    }
    //cout<<"Case #:"<<answer<<' '<<l<<' '<<r<<endl;
    return mp(l, r);
}*/

string S = "Atcod3rIsGreat";

int EditDistDP(string str1, string str2)
{
    int len1 = str1.length();
    int len2 = str2.length();

    // Create a DP array to memoize result
    // of previous computations
    int DP[2][len1 + 1];

    // To fill the DP array with 0
    memset(DP, 0, sizeof DP);

    // Base condition when second string
    // is empty then we remove all characters
    for (int i = 0; i <= len1; i++)
        DP[0][i] = i;

    // Start filling the DP
    // This loop run for every
    // character in second string
    for (int i = 1; i <= len2; i++) {
        // This loop compares the char from
        // second string with first string
        // characters
        for (int j = 0; j <= len1; j++) {
            // if first string is empty then
            // we have to perform add character
            // operation to get second string
            if (j == 0)
                DP[i % 2][j] = i;

                // if character from both string
                // is same then we do not perform any
                // operation . here i % 2 is for bound
                // the row number.
            else if (str1[j - 1] == str2[i - 1]) {
                DP[i % 2][j] = DP[(i - 1) % 2][j - 1];
            }

                // if character from both string is
                // not same then we take the minimum
                // from three specified operation
            else {
                DP[i % 2][j] = 1 + min(DP[(i - 1) % 2][j],
                                       min(DP[i % 2][j - 1],
                                           DP[(i - 1) % 2][j - 1]));
            }
        }
    }

    // after complete fill the DP array
    // if the len2 is even then we end
    // up in the 0th row else we end up
    // in the 1th row so we take len2 % 2
    // to get row
    return DP[len2 % 2][len1];
}


int ask(string s)
{
    cout<<"? "<<s<<endl;
    int res;
    cin>>res;
    /*int res = EditDistDP(s, S);
    cout<<res<<endl;*/
    return res;
}

void answer(string s)
{
    cout<<"! "<<s<<endl;
    exit(0);
}

int N;

bool check(string s)
{
    return (ask(s)==N - s.size());
}


vector<string> kek;

string merge(string s, string t)
{
    int pos = 0;
    for (auto c: t)
    {
        while (pos<s.size() && !check( s.substr(0, pos) + c + s.substr(pos))) pos++;
        s = s.substr(0, pos) + c + s.substr(pos);
        pos++;
    }
    return s;
}

string solve(int l, int r)
{
    if (l==r) return kek[l];
    int mid = (l+r)/2;
    string ans = merge(solve(l, mid), solve(mid+1, r));
    //cout<<l<<' '<<r<<": "<<ans<<endl;
    return ans;
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);

    int minn = 1e9;

    vector<char> C;

    for (char c = 'a'; c<='z'; c++) C.push_back(c);
    for (char c = 'A'; c<='Z'; c++) C.push_back(c);
    for (char c = '0'; c<='9'; c++) C.push_back(c);

    //C = {'a', 'b'};

    vector<int> tmp;
    for (int i = 0; i<C.size(); i++)
    {
        string s;
        for (int j = 0; j<128; j++) s+=C[i];
        tmp.push_back(ask(s));
    }

    int tot = 0;
    for (auto it: tmp) tot += it;

    //sum of(128 - N) - #a = 62*(128-N) - N = 128*62 - 63*N;

    int sz = C.size();

    N = (128*sz - tot);

    //cout<<"N: "<<N<<endl;

    for (int i = 0; i<C.size(); i++)
    {
        int cnt = 128 - tmp[i];
        string s;
        for (int j = 0; j<cnt; j++) s+=C[i];
        if (s.size()>0) kek.push_back(s);
    }

    /*for (auto it: kek) cout<<it<<' ';
    cout<<endl;*/

    answer(solve(0, kek.size()-1));




}



Measured memory_bytes: 3752