#include <bits/stdc++.h>
using namespace std;
const int INF = 2147483647;
const long long LLINF = 9223372036854775807LL;
struct Response {
  int fr, to;
  vector<string> vs;
  Response(int fr, int to, const vector<string>& vs) : fr(fr), to(to), vs(vs) {}
};
Response ask(int l, int r) {
  cout << "? " << l << " " << r << endl;
  vector<string> result;
  for (int i = l; i <= r; ++i)
    for (int j = i; j <= r; ++j) {
      string curs;
      cin >> curs;
      result.push_back(curs);
    }
  return Response(l - 1, r - 1, result);
}
void fin(string s) {
  cout << "! " << s << endl;
  exit(0);
}
struct St {
  multiset<char> ms;
  St() = default;
  explicit St(const vector<char>& v) : ms(v.begin(), v.end()) {}
  St inters(const St& oth) const {
    vector<char> res(int((ms).size()));
    res.erase(set_intersection(ms.begin(), ms.end(), oth.ms.begin(),
                               oth.ms.end(), res.begin()),
              res.end());
    return St(res);
  }
  St subtract(const St& oth) const {
    vector<char> res(int((ms).size()));
    res.erase(set_difference(ms.begin(), ms.end(), oth.ms.begin(), oth.ms.end(),
                             res.begin()),
              res.end());
    return St(res);
  }
  bool operator==(const St& oth) const { return ms == oth.ms; }
  bool operator!=(const St& oth) const { return ms != oth.ms; }
  bool operator<(const St& oth) const { return ms < oth.ms; }
};
int n;
const int maxn = 110;
char fc[maxn];
void update_info(int wlen, const Response& resp) {
  if (wlen >= resp.to - resp.fr + 1) return;
  St known;
  for (int i = resp.fr; i + wlen - 1 <= resp.to; ++i) {
    int wfr = i;
    int wto = i + wlen - 1;
    for (int j = 0; j <= resp.to; ++j) {
      if (j >= wfr && j <= wto) continue;
      if (fc[j] == 0) continue;
      known.ms.insert(fc[j]);
    }
  }
  string full_str = *max_element(resp.vs.begin(), resp.vs.end(),
                                 [](const string& x, const string& y) {
                                   return int((x).size()) < int((y).size());
                                 });
  St from_req;
  for (const string& s : resp.vs) {
    if (int((s).size()) != wlen) continue;
    for (char c : St(vector<char>(full_str.begin(), full_str.end()))
                      .subtract(St(vector<char>(s.begin(), s.end())))
                      .ms)
      from_req.ms.insert(c);
  }
  auto rm = from_req.subtract(known).ms;
  if (int((rm).size()) != 1) return;
  char curc = *rm.begin();
  for (int i = resp.fr; i <= resp.to; ++i) {
    if (i <= resp.fr + wlen - 1 && i >= resp.to - wlen + 1) continue;
    if (fc[i] == 0) fc[i] = curc;
  }
}
int main() {
  cin >> n;
  if (n < 3) {
    Response r1 = ask(1, n);
    if (n == 1) fin(r1.vs[0]);
    Response r2 = ask(1, n - 1);
    string s1 = *max_element(r1.vs.begin(), r1.vs.end(),
                             [](const string& x, const string& y) {
                               return int((x).size()) < int((y).size());
                             });
    string s2 = *max_element(r2.vs.begin(), r2.vs.end(),
                             [](const string& x, const string& y) {
                               return int((x).size()) < int((y).size());
                             });
    fc[n - 1] = *St(vector<char>(s1.begin(), s1.end()))
                     .subtract(St(vector<char>(s2.begin(), s2.end())))
                     .ms.begin();
    for (int wlen = n - 1; wlen >= 1; --wlen) {
      update_info(wlen, r2);
      update_info(wlen, r1);
    }
    string res(fc);
    fin(res);
    return 0;
  }
  int m1 = n / 2;
  Response r1 = ask(1, m1 + 1);
  Response r2 = ask(1, m1);
  string s1 = *max_element(r1.vs.begin(), r1.vs.end(),
                           [](const string& x, const string& y) {
                             return int((x).size()) < int((y).size());
                           });
  string s2 = *max_element(r2.vs.begin(), r2.vs.end(),
                           [](const string& x, const string& y) {
                             return int((x).size()) < int((y).size());
                           });
  fc[m1] = *St(vector<char>(s1.begin(), s1.end()))
                .subtract(St(vector<char>(s2.begin(), s2.end())))
                .ms.begin();
  for (int wlen = m1; wlen >= 1; --wlen) {
    update_info(wlen, r2);
    update_info(wlen, r1);
  }
  Response r3 = ask(1, n);
  for (int wlen = n - 1; wlen >= 1; --wlen) {
    update_info(wlen, r3);
  }
  string res(fc);
  fin(res);
  return 0;
}
