/*
Main AC Solution, O(N)
*/

//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;

const int MN = 5*TEN(5);

string input() {
    int n;
    assert(scanf("%d", &n));
    static char buf[2*MN + 10];
    assert(scanf("%s", buf));
    return string(buf);
}

V<string> split(string s) {
    int n = int(s.size());
    V<int> idxs;
    int he = 0;
    for (int i = 0; i < n; i++) {
        if (s[i] == 'a') he++;
        else he--;
        if (he == 0) idxs.push_back(i+1);
    }
    V<string> res;
    int bk = 0;
    for (auto d: idxs) {
        res.push_back(s.substr(bk, d-bk));
        bk = d;
    }
//    cerr << "SPLITTED: " << res.size() << endl;
    return res;
}

mt19937 gen;
void reseed(ll seed) {
    gen = mt19937(seed);
    for (int i = 0; i < 10000; i++) {
        gen(); // skip
    }
}

ll rand_int(ll l, ll r) { //[l, r]
    using D = uniform_int_distribution<ll>;
    assert(l <= r);
    return D(l, r)(gen);
}

string rand_lower_string(int n, int up = 26) {
    string s = "";
    for (int i = 0; i < n; i++) {
        s += 'a' + rand_int(0, up-1);
    }
    return s;
}

template<class T> void myshuffle(T &v) {
    shuffle(begin(v), end(v), gen);
}

string to_non_neg(string s) {
    string t;
    bool neg = false;
    int he = 0;
    for (char c: s) {        
        if (neg) {
            if (c == 'a') c = 'b';
            else c = 'a';
        }
        if (he == 0 && c == 'a') {
            c = 'b';
            neg = !neg;
        }
        if (c == 'b') he++;
        else he--;
        t += c;
    }
    return t;
}

string rand_ab(int n) {
    string s = string(n-1, 'a') + string(n-1, 'b');
    myshuffle(s);
    s = to_non_neg(s);
    reverse(begin(s), end(s));
    return "a" + s + "b";
}

string rand_ba(int n) {
    string s = string(n-1, 'a') + string(n-1, 'b');
    myshuffle(s);
    s = to_non_neg(s);
    return "b" + s + "a";
}


template<class Str>
struct SA {
    Str s;
    V<int> sa, rsa, lcp;
    SA() {}
    SA(Str _s, V<int> _sa) : s(_s), sa(_sa) {
        int n = int(s.size());
        // make rsa
        rsa = V<int>(n + 1);
        for (int i = 0; i <= n; i++) {
            rsa[sa[i]] = i;
        }
        // make lcp
        lcp = V<int>(n);
        int h = 0;
        for (int i = 0; i < n; i++) {
            int j = sa[rsa[i] - 1];
            if (h > 0) h--;
            for (; j + h < n && i + h < n; h++) {
                if (s[j + h] != s[i + h]) break;
            }
            lcp[rsa[i] - 1] = h;
        }
    }
};

template<class Str>
V<int> doublingSA(Str s) {
    int n = (int)s.size();
    V<int> sa(n + 1);
    V<int> rsa(n + 1);
    iota(begin(sa), end(sa), 0);
    for (int i = 0; i <= n; i++) {
        rsa[i] = i < n ? s[i] : -1;
    }
    vector<int> tmp(n + 1);
    for (int k = 1; k <= n; k *= 2) {
        auto cmp = [&](int x, int y) {
            if (rsa[x] != rsa[y]) return rsa[x] < rsa[y];
            int rx = x + k <= n ? rsa[x + k] : -1;
            int ry = y + k <= n ? rsa[y + k] : -1;
            return rx < ry;
        };
        sort(begin(sa), end(sa), cmp);
        tmp[sa[0]] = 0;
        for (int i = 1; i <= n; i++) {
            tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
        }
        copy(begin(tmp), end(tmp), begin(rsa));
    }
    return sa;
}

string solve(string s) {
    int n = int(s.size()) / 2; assert(s.size() % 2 == 0);
    
    V<int> aidx(n), bidx(n);
    {
        int ac = 0, bc = 0;
        for (int i = 0; i < 2*n; i++) {
            if (s[i] == 'a') {
                aidx[ac++] = i;
            } else {
                bidx[bc++] = i;
            }
        }
    }

    if (s[0] == 'a') {
        string ans;
        int idx = 0;
        while (idx < n) {
            ans += "ab";
            int pos = bidx[idx];
            while (idx < n && aidx[idx] < pos) idx++;
        }
        return ans;
    }

    auto sa = SA<string>(s, doublingSA(s));

    V<int> bc(2*n+1);
    bc[0] = 0;
    for (int i = 0; i < 2*n; i++) bc[i+1] = bc[i] + (s[i] == 'b' ? 1 : 0);

    using P = pair<int, int>; // prefix b, sa
    P ans = P(-1, -1);
    for (int i = 0; i < n; i++) {
        int l = bidx[i], r = aidx[i];
        int bx = bc[r] - bc[l];
        P res = P(bx, sa.rsa[r]);
        ans = max(ans, res);
    }
    assert(ans.first >= 0);
    return string(ans.first, 'b') + s.substr(sa.sa[ans.second]);
}


int main() {
    string s = input();
    auto v = split(s);

    V<string> ans;
    for (auto t: v) {
        t = solve(t);
        while (ans.size()) {
            if (ans.back()[0] == 'a' && t[0] == 'a') break;
            if (ans.back() >= t) break;
            ans.pop_back();
        }
        ans.push_back(t);
    }
    string res;
    for (auto t: ans) res += t;
    cout << res << endl;
    return 0;
}


Measured memory_bytes: 640