#include <bits/stdc++.h>
template <class t>
inline void read(t &s) {
  s = 0;
  register int f = 1;
  register char c = getchar();
  while (!isdigit(c)) {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (isdigit(c)) s = (s << 3) + (s << 1) + (c ^ 48), c = getchar();
  s *= f;
  return;
}
template <class t, class... A>
inline void read(t &x, A &...a) {
  read(x);
  read(a...);
}
template <class t>
inline void write(t x) {
  if (x < 0) putchar('-'), x = -x;
  int buf[21], top = 0;
  while (x) buf[++top] = x % 10, x /= 10;
  if (!top) buf[++top] = 0;
  while (top) putchar(buf[top--] ^ '0');
  return;
}
inline void setIn(std::string s) {
  freopen(s.c_str(), "r", stdin);
  return;
}
inline void setOut(std::string s) {
  freopen(s.c_str(), "w", stdout);
  return;
}
inline void setIO(std::string s = "") {
  setIn(s + ".in");
  setOut(s + ".out");
  return;
}
template <class t>
inline bool ckmin(t &x, t y) {
  if (x > y) {
    x = y;
    return 1;
  }
  return 0;
}
template <class t>
inline bool ckmax(t &x, t y) {
  if (x < y) {
    x = y;
    return 1;
  }
  return 0;
}
inline int lowbit(int x) { return x & (-x); }
std::multiset<std::string> S;
namespace GEN {
std::string str;
inline std::vector<std::string> ASK(int l, int r) {
  std::vector<std::string> T;
  --l, --r;
  for (int i = l; i <= r; ++i) {
    std::string s = "";
    for (int j = i; j <= r; ++j) s += str[j], T.push_back(s);
  }
  std::random_shuffle((T).begin(), (T).end());
  for (auto &i : T) std::random_shuffle((i).begin(), (i).end());
  return T;
}
inline void GOT(std::string s) {
  if (s != str)
    42;
  else
    42;
}
}  // namespace GEN
inline std::vector<std::string> ask(int l, int r) {
  std::printf("? %d %d\n", l, r), fflush(stdout);
  std::vector<std::string> res;
  std::string s;
  for (int i = l; i <= r; ++i)
    for (int j = i; j <= r; ++j) std::cin >> s, res.push_back(s);
  return res;
}
inline void got(std::string s) {
  std::printf("! %s\n", s.c_str()), fflush(stdout);
  exit(0);
}
char Ans[105];
int f[105][255];
signed main(void) {
  srand(time(NULL));
  int n;
  read(n);
  if (n == 1) got(ask(1, n)[0]);
  for (;;) {
    std::multiset<std::string> T;
    std::vector<std::string> dr = ask(1, n / 2);
    if (n / 2 == 1) {
      Ans[1] = dr[0][0];
      break;
    }
    for (auto i : dr) std::sort((i).begin(), (i).end()), T.insert(i);
    dr = ask(2, n / 2);
    for (auto i : dr) std::sort((i).begin(), (i).end()), T.erase(T.find(i));
    dr.clear();
    for (auto i : T) dr.push_back(i);
    std::sort((dr).begin(), (dr).end(), [&](std::string &a, std::string &b) {
      return a.length() < b.length();
    });
    int bk[255], bkT[255];
    std::memset(bk, 0, sizeof bk);
    int pos = 0;
    for (auto i : dr) {
      std::memcpy(bkT, bk, sizeof bk);
      register char cur = 0;
      for (auto j : i)
        if (!(bkT[(int)j]--)) {
          cur = j;
          break;
        }
      Ans[++pos] = cur, ++bk[(int)cur];
    }
    break;
  }
  std::vector<std::string> dr = ask(1, n);
  for (auto i : dr)
    for (auto j : i) ++f[(int)i.length()][(int)j];
  for (int i = (n - 1) >> 1; ~i; --i) {
    int bk1[255];
    std::memset(bk1, 0, sizeof bk1);
    for (int j = i + 1; j <= n - i; ++j) ++bk1[Ans[j]];
    for (char x = 'a'; x <= 'z'; ++x)
      if (bk1[x] != f[i + 1][x] - f[i][x]) Ans[n - i] = x;
  }
  std::string ANS = "";
  for (int i = 1; i <= n; ++i) ANS += Ans[i];
  got(ANS);
  return 0;
}
