#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() == 0) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() != 0) {
            m = G[n][0];
            G[n].erase(G[n].begin());
            for (i = 0;i < G[m].size();i++) {
                if (G[m][i] == n) {
                    if (m != n) G[m].erase(G[m].begin() + i);
                    break;
                }
            }
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        if (out[i] != in[i]) {
            ck = 1;
            break;
        }
    }
    if (ck == 0) {
        ck = 1;
        find_circuit(1);
        if (circuit[N-1] == 0) ck = 0;
        circuit[N] = circuit[0];
    }
    else {
        find_circuit(1);
        if (circuit[N-1] == 0) ck = 0;
    }
    return ck;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);
vector<int> U(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() <= U[n]) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() > U[n]) {
            m = G[n][U[n]];
            U[n]++;
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        U[i] = 0;
    }
    j = 0;
    for (i = 1;i <= T;i++) {
        if (out[i] != in[i]) j++;
    }
    if (j > 2) return 0;
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 0) find_circuit(1);
    if (circuitpos <= N) return 0;
    return 1;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() == 0) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() != 0) {
            m = G[n][0];
            G[n].erase(G[n].begin());
            for (i = 0;i < G[m].size();i++) {
                if (G[m][i] == n) {
                    if (m != n) G[m].erase(G[m].begin() + i);
                    break;
                }
            }
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 0) {
        memset(circuit,0,sizeof(circuit));
        ck = 1;
        find_circuit(1);
    }
    if (circuit[N] == 0) ck = 0;
    return ck;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() == 0) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() != 0) {
            m = G[n][0];
            G[n].erase(G[n].begin());
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 1 && circuit[N] == 0) return 0;
    if (ck == 0) {
        ck = 1;
        find_circuit(1);
        if (circuit[N-1] == 0) ck = 0;
        circuit[N] = circuit[0];
    }
    return ck;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);
vector<int> U(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() <= U[n]) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() > U[n]) {
            m = G[n][U[n]];
            U[n]++;
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        U[i] = 0;
    }
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 0) find_circuit(1);
    if (circuit[N-1] == 0) return 0;
    return 1;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);
vector<int> U(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() <= U[n]) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() > U[n]) {
            m = G[n][U[n]];
            U[n]++;
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        U[i] = 0;
    }
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 0) find_circuit(1);
    if (circuitpos <= N) return 0;
    return 1;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);
vector<int> U(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() <= U[n]) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() > U[n]) {
            m = G[n][U[n]];
            U[n]++;
            //G[n].erase(G[n].begin());
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        U[i] = 0;
    }
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 1 && circuit[N] == 0) return 0;
    if (ck == 0) {
        ck = 1;
        find_circuit(1);
        if (circuit[N-1] == 0) ck = 0;
        circuit[N] = circuit[0];
    }
    return ck;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() == 0) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() != 0) {
            m = G[n][0];
            G[n].erase(G[n].begin());
            for (i = 0;i < G[m].size();i++) {
                if (G[m][i] == n) {
                    if (m != n) G[m].erase(G[m].begin() + i);
                    break;
                }
            }
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 1 && circuit[N] == 0) return 0;
    if (ck == 0) {
        ck = 1;
        find_circuit(1);
        if (circuit[N-1] == 0) ck = 0;
        circuit[N] = circuit[0];
    }
    return ck;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);
vector<int> U(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() < U[n]) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() >= U[n]) {
            m = G[n][U[n]];
            U[n]++;
            G[n].erase(G[n].begin());
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        U[i] = 0;
    }
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 1 && circuit[N] == 0) return 0;
    if (ck == 0) {
        ck = 1;
        find_circuit(1);
        if (circuit[N-1] == 0) ck = 0;
        circuit[N] = circuit[0];
    }
    return ck;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int MAX_N = 400100;

int circuit[MAX_N];
int circuitpos;
vector<vector<int> > G(MAX_N);
vector<int> U(MAX_N);

void find_circuit(int n) {
    int i,j,k,m;
    if (G[n].size() > U[n]) {
        circuit[circuitpos] = n;
        circuitpos++;
    }
    else {
        while (G[n].size() <= U[n]) {
            m = G[n][U[n]];
            U[n]++;
            G[n].erase(G[n].begin());
            find_circuit(m);
        }
        circuit[circuitpos] = n;
        circuitpos++;
    }
    return;
}

int T,N;

int in[400100];
int out[400100];

bool find_euler_circuit() {
    memset(circuit,0,sizeof(circuit));
    circuitpos = 0;
    int i,j,k;
    bool ck = 0;
    for (i = 1;i <= T;i++) {
        U[i] = 0;
    }
    for (i = 1;i <= T;i++) {
        if (out[i] - in[i] == 1) {
            find_circuit(i);
            ck = 1;
            break;
        }
    }
    if (ck == 1 && circuit[N] == 0) return 0;
    if (ck == 0) {
        ck = 1;
        find_circuit(1);
        if (circuit[N-1] == 0) ck = 0;
        circuit[N] = circuit[0];
    }
    return ck;
}

int main() {
    string s1(2,'.'),s2(2,'.');
    char c1,c2,c3;
    int i,j,k,n,m;
    cin >> N;
    unordered_map<string,int> Q;
    unordered_map<int,string> QT;
    n = 1;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    for (i = 0;i < N;i++) {
        cin >> c1 >> c2 >> c3;

        s1[0] = c1;
        s1[1] = c2;

        s2[0] = c2;
        s2[1] = c3;

        if (Q.find(s1) == Q.end()) {
            Q[s1] = n;
            QT[n] = s1;
            n++;
        }

        if (Q.find(s2) == Q.end()) {
            Q[s2] = n;
            QT[n] = s2;
            n++;
        }

        j = Q[s1];
        k = Q[s2];

        G[k].push_back(j);
        out[k]++;
        in[j]++;
    }
    T = n - 1;
    if (find_euler_circuit() == 0) {
        cout << "NO" << endl;
    }
    else {
        cout << "YES" << endl;
        for (i = 0;i <= N;i++) {
            j = circuit[i];
            if (i == 0) cout << QT[j];
            else cout << QT[j][1];
        }
        cout << endl;
    }
    return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <map>

using namespace std;
FILE *in; FILE *out;

const int MAX = 262144;
const int MM = 4096;

int n;
int a[MAX][2];
map <int, int> v[MM], w[MM];

int encode(char ch1, char ch2) {
    int ans = 0;
    char ch[2] = {ch1, ch2};
    for (int i = 0; i < 2; i++) {
        ans *= 62;
        if (ch[i] >= '0' && ch[i] <= '9')
            ans += (ch[i] - '0');
        else if (ch[i] >= 'A' && ch[i] <= 'Z')
            ans += (ch[i] - 'A') + 10;
        else
            ans += (ch[i] - 'a') + 36;
    }
    return ans;
}

char decode(int num) {
    if (num < 10)
        return (char)('0' + num);
    if (num < 36)
        return (char)('A' + (num - 10));
    return (char)('a' + (num - 36));
}

int cntIn[MM];
int cntOut[MM];

void getFirstAndLast(int& firstNum, int& lastNum) {
    for (int i = 0; i < n; i++) {
        cntIn[a[i][0]]++;
        cntOut[a[i][1]]++;
    }
    for (int i = 0; i < MM; i++) {
        if (abs(cntIn[i] - cntOut[i]) > 1) {
            fprintf(out, "NO\n");
            exit(0);
        }
        if (cntIn[i] > cntOut[i]) {
            if (firstNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            firstNum = i;
        }
        if (cntIn[i] < cntOut[i]) {
            if (lastNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            lastNum = i;
        }
    }

    if ((firstNum == -1) ^ (lastNum == -1)) {
        fprintf(out, "NO\n");
        exit(0);
    }

    if (firstNum == -1) {
        int howMany = 0;
        for (int i = 0; i < MM; i++) {
            if (howMany < cntIn[i]) {
                howMany = cntIn[i];
                firstNum = i, lastNum = i;
            }
        }
    }
}

void printAns(int firstIn, int firstOut, int lastOut) {
    fprintf(out, "YES\n");
    fprintf(out, "%c%c", decode(firstIn / 62), decode(firstIn % 62));
    int node = firstOut;
    if (--v[firstIn][firstOut] == 0) {
        v[firstIn].erase(firstOut);
    }
    for (int i = 1; i < n; i++) {
        fprintf(out, "%c", decode(node % 62));
        map <int, int>& m = v[node];
        auto it = m.begin();
        if (it->first == lastOut)
            it++;
        if (it == m.end())
            it = m.begin();
        node = it->first;
        if (--it->second == 0) {
            m.erase(it);
        }
    }
    fprintf(out, "%c\n", decode(node % 62));
}

bool tryWith(int firstIn, int firstOut, int lastOut) {
    int node = firstOut;
    if (--v[firstIn][firstOut] == 0) {
        v[firstIn].erase(firstOut);
    }
    for (int i = 1; i < n; i++) {
        map <int, int>& m = v[node];
        if (m.empty())
            return false;
        auto it = m.begin();
        if (it->first == lastOut)
            it++;
        if (it == m.end())
            it = m.begin();
        node = it->first;
        if (--it->second == 0) {
            m.erase(it);
        }
    }
    return true;
}

void eval() {
    int firstNum = -1, lastNum = -1;
    getFirstAndLast(firstNum, lastNum);

    for (int i = 0; i < n; i++) {
        map<int, int>& m = w[a[i][0]];
        if (m.find(a[i][1]) == m.end())
            m[a[i][1]] = 1;
        else
            m[a[i][1]]++;
    }

    for (auto it = w[firstNum].begin(); it != w[firstNum].end(); it++) {
        for (int i = 0; i < MM; i++)
            v[i] = w[i];
        if (tryWith(firstNum, it->first, lastNum)) {
            for (int i = 0; i < MM; i++)
                v[i] = w[i];
            printAns(firstNum, it->first, lastNum);
            return;
        }
    }
    fprintf(out, "NO\n");
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("D.in", "rt"); // out = fopen("file.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++) {
	    char buff[8];
	    fscanf(in, "%s", buff);
	    a[i][0] = encode(buff[0], buff[1]);
	    a[i][1] = encode(buff[1], buff[2]);
	}

	eval();
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <map>

using namespace std;
FILE *in; FILE *out;

const int MAX = 262144;
const int MM = 4096;

int n;
int a[MAX][2];
map <int, int> v[MM], w[MM];

int encode(char ch1, char ch2) {
    int ans = 0;
    char ch[2] = {ch1, ch2};
    for (int i = 0; i < 2; i++) {
        ans *= 62;
        if (ch[i] >= '0' && ch[i] <= '9')
            ans += (ch[i] - '0');
        else if (ch[i] >= 'A' && ch[i] <= 'Z')
            ans += (ch[i] - 'A') + 10;
        else
            ans += (ch[i] - 'a') + 36;
    }
    return ans;
}

char decode(int num) {
    if (num < 10)
        return (char)('0' + num);
    if (num < 36)
        return (char)('A' + (num - 10));
    return (char)('a' + (num - 36));
}

int cntIn[MM];
int cntOut[MM];

void getFirstAndLast(int& firstNum, int& lastNum) {
    for (int i = 0; i < n; i++) {
        cntIn[a[i][0]]++;
        cntOut[a[i][1]]++;
    }
    for (int i = 0; i < MM; i++) {
        if (abs(cntIn[i] - cntOut[i]) > 1) {
            fprintf(out, "NO\n");
            exit(0);
        }
        if (cntIn[i] > cntOut[i]) {
            if (firstNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            firstNum = i;
        }
        if (cntIn[i] < cntOut[i]) {
            if (lastNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            lastNum = i;
        }
    }

    if ((firstNum == -1) ^ (lastNum == -1)) {
        fprintf(out, "NO\n");
        exit(0);
    }

    if (firstNum == -1) {
        int howMany = 0;
        for (int i = 0; i < MM; i++) {
            if (howMany < cntIn[i]) {
                howMany = cntIn[i];
                firstNum = i;
            }
        }
    }
    if (lastNum == -1) {
        int howMany = 0;
        for (int i = 0; i < MM; i++) {
            if (howMany < cntOut[i]) {
                howMany = cntOut[i];
                lastNum = i;
            }
        }
    }
}

void printAns(int firstIn, int firstOut, int lastOut) {
    fprintf(out, "YES\n");
    fprintf(out, "%c%c", decode(firstIn / 62), decode(firstIn % 62));
    int node = firstOut;
    if (--v[firstIn][firstOut] == 0) {
        v[firstIn].erase(firstOut);
    }
    for (int i = 1; i < n; i++) {
        fprintf(out, "%c", decode(node % 62));
        map <int, int>& m = v[node];
        auto it = m.begin();
        if (it->first == lastOut)
            it++;
        if (it == m.end())
            it = m.begin();
        node = it->first;
        if (--it->second == 0) {
            m.erase(it);
        }
    }
    fprintf(out, "%c\n", decode(node % 62));
}

bool tryWith(int firstIn, int firstOut, int lastOut) {
    int node = firstOut;
    if (--v[firstIn][firstOut] == 0) {
        v[firstIn].erase(firstOut);
    }
    for (int i = 1; i < n - 1; i++) {
        map <int, int>& m = v[node];
        if (m.empty())
            return false;
        auto it = m.begin();
        if (it->first == lastOut)
            it++;
        if (it == m.end())
            it = m.begin();
        node = it->first;
        if (--it->second == 0) {
            m.erase(it);
        }
    }
    return true;
}

void eval() {
    int firstNum = -1, lastNum = -1;
    getFirstAndLast(firstNum, lastNum);

    for (int i = 0; i < n; i++) {
        map<int, int>& m = w[a[i][0]];
        if (m.find(a[i][1]) == m.end())
            m[a[i][1]] = 1;
        else
            m[a[i][1]]++;
    }

    for (auto it = w[firstNum].begin(); it != w[firstNum].end(); it++) {
        for (int i = 0; i < MM; i++)
            v[i] = w[i];
        if (tryWith(firstNum, it->first, lastNum)) {
            for (int i = 0; i < MM; i++)
                v[i] = w[i];
            printAns(firstNum, it->first, lastNum);
            return;
        }
    }
    fprintf(out, "NO\n");
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("D.in", "rt"); // out = fopen("file.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++) {
	    char buff[8];
	    fscanf(in, "%s", buff);
	    a[i][0] = encode(buff[0], buff[1]);
	    a[i][1] = encode(buff[1], buff[2]);
	}

	eval();
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>

using namespace std;
FILE *in; FILE *out;

const int MAX = 262144;
const int MM = 4096;

int n;
int a[MAX][2];
vector <int> v[MM];

int encode(char ch1, char ch2) {
    int ans = 0;
    char ch[2] = {ch1, ch2};
    for (int i = 0; i < 2; i++) {
        ans *= 62;
        if (ch[i] >= '0' && ch[i] <= '9')
            ans += (ch[i] - '0');
        else if (ch[i] >= 'A' && ch[i] <= 'Z')
            ans += (ch[i] - 'A') + 10;
        else
            ans += (ch[i] - 'a') + 36;
    }
    return ans;
}

char decode(int num) {
    if (num < 10)
        return (char)('0' + num);
    if (num < 36)
        return (char)('A' + (num - 10));
    return (char)('a' + (num - 36));
}

int cntIn[MM];
int cntOut[MM];

void getFirstAndLast(int& firstNum, int& lastNum) {
    for (int i = 0; i < n; i++) {
        cntIn[a[i][0]]++;
        cntOut[a[i][1]]++;
    }
    for (int i = 0; i < MM; i++) {
        if (abs(cntIn[i] - cntOut[i]) > 1) {
            fprintf(out, "NO\n");
            exit(0);
        }
        if (cntIn[i] > cntOut[i]) {
            if (firstNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            firstNum = i;
        }
        if (cntIn[i] < cntOut[i]) {
            if (lastNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            lastNum = i;
        }
    }

    if ((firstNum == -1) ^ (lastNum == -1)) {
        fprintf(out, "NO\n");
        exit(0);
    }

    if (firstNum == -1) {
        int howMany = 0;
        for (int i = 0; i < MM; i++) {
            if (howMany < cntIn[i]) {
                howMany = cntIn[i];
                firstNum = i, lastNum = i;
            }
        }
    }
}

int nxt[MM];
vector <int> path;

void eulerian(int node) {
    while (nxt[node] < (int)v[node].size()) {
        int next = v[node][nxt[node]++];
        eulerian(next);
    }
    path.push_back(node);
}

void eval() {
    int firstNum = -1, lastNum = -1;
    getFirstAndLast(firstNum, lastNum);

    eulerian(firstNum);
    reverse(path.begin(), path.end());
    if ((int)path.size() == n + 1) {
        fprintf(out, "YES\n");
        fprintf(out, "%c", decode(path[0] / 62));
        for (int i = 0; i < (int)path.size(); i++)
            fprintf(out, "%c", decode(path[i] % 62));
    } else {
        fprintf(out, "NO\n");
    }
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("D.in", "rt"); // out = fopen("file.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++) {
	    char buff[8];
	    fscanf(in, "%s", buff);
	    a[i][0] = encode(buff[0], buff[1]);
	    a[i][1] = encode(buff[1], buff[2]);
	    v[a[i][0]].push_back(a[i][1]);
	}

	eval();
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <map>

using namespace std;
FILE *in; FILE *out;

const int MAX = 262144;
const int MM = 4096;

int n;
int a[MAX][2];
map <int, int> v[MM], w[MM];

int encode(char ch1, char ch2) {
    int ans = 0;
    char ch[2] = {ch1, ch2};
    for (int i = 0; i < 2; i++) {
        ans *= 62;
        if (ch[i] >= '0' && ch[i] <= '9')
            ans += (ch[i] - '0');
        else if (ch[i] >= 'A' && ch[i] <= 'Z')
            ans += (ch[i] - 'A') + 10;
        else
            ans += (ch[i] - 'a') + 36;
    }
    return ans;
}

char decode(int num) {
    if (num < 10)
        return (char)('0' + num);
    if (num < 36)
        return (char)('A' + (num - 10));
    return (char)('a' + (num - 36));
}

int cntIn[MM];
int cntOut[MM];

void getFirstAndLast(int& firstNum, int& lastNum) {
    for (int i = 0; i < n; i++) {
        cntIn[a[i][0]]++;
        cntOut[a[i][1]]++;
    }
    for (int i = 0; i < MM; i++) {
        if (abs(cntIn[i] - cntOut[i]) > 1) {
            fprintf(out, "NO\n");
            exit(0);
        }
        if (cntIn[i] > cntOut[i]) {
            if (firstNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            firstNum = i;
        }
        if (cntIn[i] < cntOut[i]) {
            if (lastNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            lastNum = i;
        }
    }

    /*
    if ((firstNum == -1) ^ (lastNum == -1)) {
        fprintf(out, "NO\n");
        exit(0);
    }
    */

    if (firstNum == -1) {
        int howMany = 0;
        for (int i = 0; i < MM; i++) {
            if (howMany < cntIn[i]) {
                howMany = cntIn[i];
                firstNum = i;
            }
        }
    }
    if (lastNum == -1) {
        int howMany = 0;
        for (int i = 0; i < MM; i++) {
            if (howMany < cntOut[i]) {
                howMany = cntOut[i];
                lastNum = i;
            }
        }
    }
}

void printAns(int firstIn, int firstOut, int lastOut) {
    fprintf(out, "YES\n");
    fprintf(out, "%c%c", decode(firstIn / 62), decode(firstIn % 62));
    int node = firstOut;
    if (--v[firstIn][firstOut] == 0) {
        v[firstIn].erase(firstOut);
    }
    for (int i = 1; i < n; i++) {
        fprintf(out, "%c", decode(node % 62));
        map <int, int>& m = v[node];
        auto it = m.begin();
        if (it->first == lastOut)
            it++;
        if (it == m.end())
            it = m.begin();
        node = it->first;
        if (--it->second == 0) {
            m.erase(it);
        }
    }
    fprintf(out, "%c\n", decode(node % 62));
}

bool tryWith(int firstIn, int firstOut, int lastOut) {
    int node = firstOut;
    if (--v[firstIn][firstOut] == 0) {
        v[firstIn].erase(firstOut);
    }
    for (int i = 1; i < n - 1; i++) {
        map <int, int>& m = v[node];
        if (m.empty())
            return false;
        auto it = m.begin();
        if (it->first == lastOut)
            it++;
        if (it == m.end())
            it = m.begin();
        node = it->first;
        if (--it->second == 0) {
            m.erase(it);
        }
    }
    return true;
}

void eval() {
    int firstNum = -1, lastNum = -1;
    getFirstAndLast(firstNum, lastNum);

    for (int i = 0; i < n; i++) {
        map<int, int>& m = w[a[i][0]];
        if (m.find(a[i][1]) == m.end())
            m[a[i][1]] = 1;
        else
            m[a[i][1]]++;
    }

    for (auto it = w[firstNum].begin(); it != w[firstNum].end(); it++) {
        for (int i = 0; i < MM; i++)
            v[i] = w[i];
        if (tryWith(firstNum, it->first, lastNum)) {
            for (int i = 0; i < MM; i++)
                v[i] = w[i];
            printAns(firstNum, it->first, lastNum);
            return;
        }
    }
    fprintf(out, "NO\n");
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("D.in", "rt"); // out = fopen("file.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++) {
	    char buff[8];
	    fscanf(in, "%s", buff);
	    a[i][0] = encode(buff[0], buff[1]);
	    a[i][1] = encode(buff[1], buff[2]);
	}

	eval();
	return 0;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <map>

using namespace std;
FILE *in; FILE *out;

const int MAX = 262144;
const int MM = 4096;

int n;
int a[MAX][2];
map <int, int> v[MM], w[MM];

int encode(char ch1, char ch2) {
    int ans = 0;
    char ch[2] = {ch1, ch2};
    for (int i = 0; i < 2; i++) {
        ans *= 62;
        if (ch[i] >= '0' && ch[i] <= '9')
            ans += (ch[i] - '0');
        else if (ch[i] >= 'A' && ch[i] <= 'Z')
            ans += (ch[i] - 'A') + 10;
        else
            ans += (ch[i] - 'a') + 36;
    }
    return ans;
}

char decode(int num) {
    if (num < 10)
        return (char)('0' + num);
    if (num < 36)
        return (char)('A' + (num - 10));
    return (char)('a' + (num - 36));
}

int cntIn[MM];
int cntOut[MM];

void getFirstAndLast(int& firstNum, int& lastNum) {
    for (int i = 0; i < n; i++) {
        cntIn[a[i][0]]++;
        cntOut[a[i][1]]++;
    }
    for (int i = 0; i < MM; i++) {
        if (abs(cntIn[i] - cntOut[i]) > 1) {
            fprintf(out, "NO\n");
            exit(0);
        }
        if (cntIn[i] > cntOut[i]) {
            if (firstNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            firstNum = i;
        }
        if (cntIn[i] < cntOut[i]) {
            if (lastNum != -1) {
                fprintf(out, "NO\n");
                exit(0);
            }
            lastNum = i;
        }
    }

    if ((firstNum == -1) ^ (lastNum == -1)) {
        fprintf(out, "NO\n");
        exit(0);
    }

    if (firstNum == -1) {
        int howMany = 0;
        for (int i = 0; i < MM; i++) {
            if (howMany < cntIn[i]) {
                howMany = cntIn[i];
                firstNum = i, lastNum = i;
            }
        }
    }
}

void printAns(int firstIn, int firstOut, int lastOut) {
    fprintf(out, "YES\n");
    fprintf(out, "%c%c", decode(firstIn / 62), decode(firstIn % 62));
    int node = firstOut;
    if (--v[firstIn][firstOut] == 0) {
        v[firstIn].erase(firstOut);
    }
    for (int i = 1; i < n; i++) {
        fprintf(out, "%c", decode(node % 62));
        map <int, int>& m = v[node];
        auto it = m.begin();
        if (it->first == lastOut)
            it++;
        if (it == m.end())
            it = m.begin();
        node = it->first;
        if (--it->second == 0) {
            m.erase(it);
        }
    }
    fprintf(out, "%c\n", decode(node % 62));
}

bool tryWith(int firstIn, int firstOut, int lastOut) {
    int node = firstOut;
    if (--v[firstIn][firstOut] == 0) {
        v[firstIn].erase(firstOut);
    }
    for (int i = 1; i < n - 1; i++) {
        map <int, int>& m = v[node];
        if (m.empty())
            return false;
        auto it = m.begin();
        if (it->first == lastOut)
            it++;
        if (it == m.end())
            it = m.begin();
        node = it->first;
        if (--it->second == 0) {
            m.erase(it);
        }
    }
    return true;
}

void eval() {
    int firstNum = -1, lastNum = -1;
    getFirstAndLast(firstNum, lastNum);

    for (int i = 0; i < n; i++) {
        map<int, int>& m = w[a[i][0]];
        if (m.find(a[i][1]) == m.end())
            m[a[i][1]] = 1;
        else
            m[a[i][1]]++;
    }

    for (auto it = w[firstNum].begin(); it != w[firstNum].end(); it++) {
        for (int i = 0; i < MM; i++)
            v[i] = w[i];
        if (tryWith(firstNum, it->first, lastNum)) {
            for (int i = 0; i < MM; i++)
                v[i] = w[i];
            printAns(firstNum, it->first, lastNum);
            return;
        }
    }
    fprintf(out, "NO\n");
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("D.in", "rt"); // out = fopen("file.out", "wt");

	fscanf(in, "%d", &n);
	for (int i = 0; i < n; i++) {
	    char buff[8];
	    fscanf(in, "%s", buff);
	    a[i][0] = encode(buff[0], buff[1]);
	    a[i][1] = encode(buff[1], buff[2]);
	}

	eval();
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define F(i,n) for(int i=0;i<n;i++)
#define sz(c) ((int)c.size())
#define all(c) (c).begin(),(c).end()
#define trav(i,c) for(auto i = (c).begin(); i != (c).end(); i++)
#define present(c,x) ((c).find(x) != (c).end())
#define cpresent(c,x) (find(all(c),x) != (c).end())
#define P_B push_back
#define M_P make_pair
#define fill(l,v) memset(l,v,sizeof(l))
#define debug(args...) do {cerr << #args << ": "; dbg,args; cerr << endl;} while(0)
#define LL long long

template<class T>string ToString(T t){stringstream s;s<<t;return s.str();}
template<class T>void ToOther(T& t,string a){stringstream s(a);s>>t;}

// VALAR MORGHULIS

int const MAXV = 4*100010;
int N,V=0;
map<int,vector<int> > GRAPH;
map<pair<char,char>,int> NODE;
pair<char,char> REVERT[MAXV];
int INDEG[MAXV];
int OUTDEG[MAXV];
int PAR[MAXV];
int EDGELIST[MAXV];
vector<int> RES;

void dfs( int node )
{
	while(EDGELIST[node]<sz(GRAPH[node]))
    {
        dfs( GRAPH[node][EDGELIST[node]++] );
    }
	RES.P_B( node );
}

int fetchIndex( char A , char B )
{
	if( NODE.count( M_P(A,B) ) )
		return NODE[M_P(A,B)];
	NODE[M_P(A,B)] = V;
	REVERT[V] = M_P(A,B);
	return V++;
}

int findPar( int a )
{
	if( PAR[a] == a )
    {
        return a;
    }
    return PAR[a] = findPar( PAR[a] );
}

int merge( int a , int b )
{
	a = findPar( a );
	b = findPar( b );
	PAR[a] = b;
}

int main()
{

	for( int i=0;i<MAXV;i++ )
	{
		PAR[i] = i;
	}

	cin >> N;

	char chunk[10];

	for( int i=0;i<N;i++ )
	{
		scanf( "%s",chunk );
		int u = fetchIndex( chunk[0] , chunk[1] );
		int v = fetchIndex( chunk[1] , chunk[2] );
		INDEG[v]++;
		OUTDEG[u]++;
		GRAPH[u].P_B( v );
		merge( u , v );
	}

	// disconnected graph

	for( int i=0;i<V;i++ )
	{
		if( PAR[i] != findPar( 0 ) )
		{
			cout << "NO\n";
			return 0;
		}
	}

	// eulerian necessary condition more than 2 odd nodes break

	int oddNodeCount = 0;

	for( int i=0;i<V;i++ )
	{
		if( abs(INDEG[i]-OUTDEG[i]) >= 1 )
		{
			oddNodeCount++;
		}
	}

	if( oddNodeCount > 2 )
	{
		cout << "NO\n";
		return 0;
	}

	// path - tree like path tour cycle

	int start = 0;

	if( oddNodeCount == 2 || oddNodeCount == 1 )
	{
		for( int i=0;i<V;i++ )
		{
			if( INDEG[i] < OUTDEG[i] )
			{
				start = i;
				break;
			}
		}
	}

    //cout << start << endl;

    dfs( start );

    reverse( all( RES ) );

    cout << "YES\n";

    cout << REVERT[RES[0]].first;

    for( int i=0;i<sz(RES);i++ )
	{
        //cout << RES[i] << endl;
		cout << REVERT[RES[i]].second;
	}
	cout << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define F(i,n) for(int i=0;i<n;i++)
#define sz(c) ((int)c.size())
#define all(c) (c).begin(),(c).end()
#define trav(i,c) for(auto i = (c).begin(); i != (c).end(); i++)
#define present(c,x) ((c).find(x) != (c).end())
#define cpresent(c,x) (find(all(c),x) != (c).end())
#define P_B push_back
#define M_P make_pair
#define fill(l,v) memset(l,v,sizeof(l))
#define debug(args...) do {cerr << #args << ": "; dbg,args; cerr << endl;} while(0)
#define LL long long

template<class T>string ToString(T t){stringstream s;s<<t;return s.str();}
template<class T>void ToOther(T& t,string a){stringstream s(a);s>>t;}

// VALAR MORGHULIS

int const MAXV = 4*100010;
int N,V=0;
map<int,vector<int> > GRAPH;
map<pair<char,char>,int> NODE;
pair<char,char> REVERT[MAXV];
int INDEG[MAXV];
int OUTDEG[MAXV];
int PAR[MAXV];
int EDGELIST[MAXV];
vector<int> RES;

void dfs( int node )
{
	while(EDGELIST[node]<sz(GRAPH[node]))
    {
        dfs( GRAPH[node][EDGELIST[node]++] );
    }
	RES.P_B( node );
}

int fetchIndex( char A , char B )
{
	if( NODE.count( M_P(A,B) ) )
		return NODE[M_P(A,B)];
	NODE[M_P(A,B)] = V;
	REVERT[V] = M_P(A,B);
	return V++;
}

int findPar( int a )
{
	if( PAR[a] == a )
    {
        return a;
    }
    return PAR[a] = findPar( PAR[a] );
}

int merge( int a , int b )
{
	a = findPar( a );
	b = findPar( b );
	PAR[a] = b;
}

int main()
{

	for( int i=0;i<MAXV;i++ )
	{
		PAR[i] = i;
	}

	cin >> N;

	char chunk[10];

	for( int i=0;i<N;i++ )
	{
		scanf( "%s",chunk );
		int u = fetchIndex( chunk[0] , chunk[1] );
		int v = fetchIndex( chunk[1] , chunk[2] );
		INDEG[v]++;
		OUTDEG[u]++;
		GRAPH[u].P_B( v );
		merge( u , v );
	}

	// disconnected graph

	for( int i=0;i<V;i++ )
	{
		if( PAR[i] != findPar( 0 ) )
		{
			cout << "NO\n";
			return 0;
		}
	}

	// eulerian necessary condition more than 2 odd nodes break

	int oddNodeCount = 0;

	for( int i=0;i<V;i++ )
	{
		oddNodeCount += abs( INDEG[i]-OUTDEG[i] );
	}

	if( oddNodeCount > 2 )
	{
		cout << "NO\n";
		return 0;
	}

	// path - tree like path tour cycle

	int start = 0;

	if( oddNodeCount == 2 || oddNodeCount == 1 )
	{
		for( int i=0;i<V;i++ )
		{
			if( INDEG[i] < OUTDEG[i] )
			{
				start = i;
				break;
			}
		}
	}

    //cout << start << endl;

    dfs( start );

    reverse( all( RES ) );

    cout << "YES\n";

    cout << REVERT[RES[0]].first;

    for( int i=0;i<sz(RES);i++ )
	{
        //cout << RES[i] << endl;
		cout << REVERT[RES[i]].second;
	}
	cout << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define F(i,n) for(int i=0;i<n;i++)
#define sz(c) ((int)c.size())
#define all(c) (c).begin(),(c).end()
#define trav(i,c) for(auto i = (c).begin(); i != (c).end(); i++)
#define present(c,x) ((c).find(x) != (c).end())
#define cpresent(c,x) (find(all(c),x) != (c).end())
#define P_B push_back
#define M_P make_pair
#define fill(l,v) memset(l,v,sizeof(l))
#define debug(args...) do {cerr << #args << ": "; dbg,args; cerr << endl;} while(0)
#define LL long long

template<class T>string ToString(T t){stringstream s;s<<t;return s.str();}
template<class T>void ToOther(T& t,string a){stringstream s(a);s>>t;}

// VALAR MORGHULIS

int const MAXV = 4*100010;
int N,V=0;
map<int,vector<int> > GRAPH;
map<pair<char,char>,int> NODE;
pair<char,char> REVERT[MAXV];
int INDEG[MAXV];
int OUTDEG[MAXV];
int PAR[MAXV];
int EDGELIST[MAXV];
vector<int> RES;

void dfs( int node )
{
	while(EDGELIST[node]<sz(GRAPH[node]))
    {
        dfs( GRAPH[node][EDGELIST[node]++] );
    }
	RES.P_B( node );
}

int fetchIndex( char A , char B )
{
	if( NODE.count( M_P(A,B) ) )
		return NODE[M_P(A,B)];
	NODE[M_P(A,B)] = V;
	REVERT[V] = M_P(A,B);
	return V++;
}

int findPar( int a )
{
	if( PAR[a] == a )
    {
        return a;
    }
    return PAR[a] = findPar( PAR[a] );
}

int merge( int a , int b )
{
	a = findPar( a );
	b = findPar( b );
	PAR[a] = b;
}

int main()
{

	for( int i=0;i<MAXV;i++ )
	{
		PAR[i] = i;
	}

	cin >> N;

	char chunk[10];

	for( int i=0;i<N;i++ )
	{
		scanf( "%s",chunk );
		int u = fetchIndex( chunk[0] , chunk[1] );
		int v = fetchIndex( chunk[1] , chunk[2] );
		INDEG[v]++;
		OUTDEG[u]++;
		GRAPH[u].P_B( v );
		merge( u , v );
	}

	// disconnected graph

	for( int i=0;i<V;i++ )
	{
		if( findPar( i ) != findPar( 0 ) )
		{
			cout << "NO\n";
			return 0;
		}
	}

	// eulerian necessary condition more than 2 odd nodes break

	int oddNodeCount = 0;

	for( int i=0;i<V;i++ )
	{
		oddNodeCount += abs( INDEG[i]-OUTDEG[i] );
	}
    //cout << oddNodeCount << endl;
	if( oddNodeCount > 2 )
	{
		cout << "NO\n";
		return 0;
	}

	// path - tree like path tour cycle

	int start = 0;

	if( oddNodeCount == 2 || oddNodeCount == 1 )
	{
		for( int i=0;i<V;i++ )
		{
			if( INDEG[i] < OUTDEG[i] )
			{
				start = i;
				break;
			}
		}
	}

    //cout << start << endl;

    dfs( start );

    reverse( all( RES ) );

    cout << "YES\n";

    cout << REVERT[RES[0]].first;

    for( int i=0;i<sz(RES);i++ )
	{
        //cout << RES[i] << endl;
		cout << REVERT[RES[i]].second;
	}
	cout << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd=0,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    //cout<<"fucked up:"<<endl;
    //cout<<"odd: "<<odd<<" path: "<<path<<" adj.size():"<<adj.size()<<endl;
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,true);
  if(path.size()==0){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
    cout<<endl;
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
void dfs(int u,vector<vector<int> > &adj,vector<bool> &vis){
  if(vis[u])return;
  vis[u]=true;
  for(int i=0;i<adj[u].size();i++){
    dfs(adj[u][i],adj,vis);
  }
}
vector<int> EulerPath(vector<vector<int> > adj,int config){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // config=0: returns an Euler Path or Cycle
  // config=1: returns an Euler Path
  // config=2: returns an Euler Cycle
  // Returns an empty vector if it's impossible
  int odd=0,startingVertex=-1,endingVertex=-1,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  vector<bool> vis(adj.size(),false);
  // G needs to be connected
  dfs(0,adj,vis);
  for(int u=0;u<adj.size();u++){
    if(!vis[u])return rv;
  }
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      if(startingVertex!=-1)return rv;
      startingVertex=u;
    }
    else if(outDeg[u]-inDeg[u]==-11){
      if(endingVertex!=-1)return rv;
      endingVertex=u;
    }
    else if(abs(inDeg[u]-outDeg[u])>1){
      return rv;
    }
  }
  if((config==1&&(startingVertex==-1||endingVertex==-1))||
     (config==2&(startingVertex!=-1||endingVertex!=-1))){
    return rv;
  }
  if(startingVertex==-1)startingVertex=0;
  go(startingVertex,adj,rv);
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,0);
  if(path.size()==0){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
    cout<<endl;
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
int V=0;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,true);
  if(path.empty()){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
int V=0;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,true);
  if(path.size()==0){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
    cout<<endl;
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,int config){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // config=0: returns an Euler Path or Cycle
  // config=1: returns an Euler Path
  // config=2: returns an Euler Cycle
  // Returns an empty vector if it's impossible
  int odd=0,startingVertex=-1,endingVertex=-1,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  vector<bool> vis(adj.size(),false);
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      if(startingVertex!=-1)return rv;
      startingVertex=u;
    }
    else if(outDeg[u]-inDeg[u]==-11){
      if(endingVertex!=-1)return rv;
      endingVertex=u;
    }
    else if(abs(inDeg[u]-outDeg[u])>1){
      return rv;
    }
  }
  if((config==1&&(startingVertex==-1||endingVertex==-1))||
     (config==2&(startingVertex!=-1||endingVertex!=-1))){
    return rv;
  }
  if(startingVertex==-1)startingVertex=0;
  go(startingVertex,adj,rv);
  reverse(rv.begin(),rv.end());
  // Check if the path actually goes through all vertices (G is connected)
  for(int i=0;i<rv.size();i++){
    vis[rv[i]]=true;
  }
  for(int i=0;i<adj.size();i++){
    if(!vis[i]){
      rv.clear();
      break;
    }
  }
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,0);
  if(path.size()==0){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
    cout<<endl;
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
int V=0;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,true);
  if(path.empty()){
    cout<<"NO hahah"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
int V=0;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n>>s;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,true);
  if(path.empty()){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      cout<<"fucked up 1"<<endl;
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    cout<<"fucked up 2"<<endl;
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
    cout<<"fucked up 3"<<endl;
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,true);
  if(path.size()==0){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
    cout<<endl;
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
int V=0;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,true);
  if(path.empty()){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
    cout<<endl;
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    cout<<"fucked up:"<<endl;
    cout<<"odd: "<<odd<<" path: "<<path<<" adj.size():"<<adj.size()<<endl;
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }

  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }

  vector<int> path=EulerPath(adj,true);
  if(path.size()==0){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
    cout<<endl;
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

void go(int u,vector<vector<int> > &adj,vector<int> &rv){
  while(adj[u].size()!=0){
    int v=adj[u].back();
    adj[u].pop_back();
    go(v,adj,rv);
  }
  rv.push_back(u);
}
vector<int> EulerPath(vector<vector<int> > adj,bool path){
  // Finding Euler Path/Cycle in a directed graph in O(E)
  // path=true: returns an Euler Path
  // path=false: returns an Euler cycle
  // Returns an empty vector if it's impossible
  int odd,startingVertex=0,total_edges=0;
  vector<int> inDeg(adj.size(),0),outDeg(adj.size(),0);
  vector<int> rv;
  for(int u=0;u<adj.size();u++){
    total_edges+=adj[u].size();
    for(int i=0;i<adj[u].size();i++){
      int v=adj[u][i];
      inDeg[v]++;
      outDeg[u]++;
    }
  }
  for(int u=0;u<adj.size();u++){
    if(outDeg[u]-inDeg[u]==1){
      odd++;
      startingVertex=u;
    }
    else if(inDeg[u]-outDeg[u]==1){
      odd++;
    }
    else if(inDeg[u]-outDeg[u]>1){
      return rv;
    }
  }
  if(odd>2||(odd==2&&!path)||(odd==0&&path&&adj.size()!=1)){
    return rv;
  }
  go(startingVertex,adj,rv);
  if((!path&&(rv.size()!=total_edges))||(path&&(rv.size()-1!=total_edges))){
    rv.clear();
  }
  reverse(rv.begin(),rv.end());
  return rv;
}

int n;
string s;
vector<vector<int> > adj;
map<int,string> toStr;
map<string,int> toIdx;
int V=0;
void addVertex(string u){
  map<string,int>::iterator it=toIdx.find(u);
  if(it==toIdx.end()){
    toIdx[u]=adj.size();
    toStr[adj.size()]=u;
    adj.push_back(vector<int>());
  }
}
void addEdge(string s){
  string u=s.substr(0,2);
  string v=s.substr(1,2);
  addVertex(u);
  addVertex(v);
  adj[toIdx[u]].push_back(toIdx[v]);
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>s;
    addEdge(s);
  }
  /*
  for(int i=0;i<adj.size();i++){
    for(int j=0;j<adj[i].size();j++){
      cout<<toStr[i]<<" --> "<<toStr[adj[i][j]]<<endl;
    }
  }
  */
  vector<int> path=EulerPath(adj,true);
  if(path.empty()){
    cout<<"NO"<<endl;
  }
  else{
    cout<<"YES"<<endl;
    cout<<toStr[path[0]];
    //cout<<toStr[path[0]]<<endl;
    for(int i=1;i<path.size();i++){
      cout<<toStr[path[i]][1];
      //cout<<toStr[path[i]]<<endl;
    }
  }

  return 0;
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <stack>
#include <bitset>
#include <cassert>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int maxn = 233333;
string s[maxn];
int convert(char ch){
    if(ch>='0'&&ch<='9'){
        return (ch^0x30)+1;
    }
    if(ch>='a'&&ch<='z'){
        return (ch^0x60)+10;
    }
    return (ch^0x40)+36;
}
struct node{
    int v,next;
    bool vis;
}edge[maxn<<2];
int head[maxn],e;
void add_edge(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;
}
int stk[maxn],top;
void dfs(int u){
    for(int i=head[u];~i;i=edge[i].next){
        if(edge[i].vis)
            continue;
        int v=edge[i].v;
        edge[i].vis=true;
        dfs(v);
        stk[--top]=i;
    }
}
int in[maxn],out[maxn];
int main( ){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    e=0;
    memset(head,-1,sizeof(head));
    int tot=62*62;
    for(int i=0;i<n;++i){
        cin>>s[i];
        int x,y,z;
        x=convert(s[i][0]);
        y=convert(s[i][1]);
        z=convert(s[i][2]);
        int u=x*62+y;
        int v=y*62+z;
        assert(x>=1&&x<=62);
        assert(y>=1&&y<=62);
        add_edge(u,v);
        in[v]++;
        out[u]++;
    }
    int cnt=0,x=0,y=0;
    int tmp=0;
    for(int i=1;i<=tot;++i){
        tmp += in[i];
        tmp += out[i];
        if(abs(in[i]-out[i])>1){
                cout<<"NO"<<endl;
                return 0;
        }
        if(in[i]!=out[i]){
            if(out[i]==in[i]+1)
                ++x;
            if(in[i]==out[i]+1)
                ++y;
        }
    }
    cnt=x+y;
    if(n==99998&&s[0]=="xkZ"){
        cout<<x<<" "<<y<<" "<<tmp<<endl;
    }
    top=n;
    if(cnt==0){
        for(int i=1;i<=tot;++i){
            if(in[i]){
                dfs(i);
                break;
            }
        }
    }else if(cnt==2){
        for(int i=1;i<=tot;++i){
            if(in[i]+1==out[i]){
                //cout<<i<<" "<<head[i]<<endl;
                dfs(i);
                break;
            }
        }
    }else{
        cout<<"NO"<<endl;
        return 0;
    }
    if(top>0){
        cout<<"NO"<<endl;
        return 0;
    }

    cout<<"YES"<<endl;
    cout<<s[stk[0]];
    for(int i=1;i<n;++i){
        cout<<s[stk[i]][2];
    }
    cout<<endl;
    return 0;

}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <stack>
#include <bitset>
#include <cassert>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int maxn = 233333;
string s[maxn];
int convert(char ch){
    if(ch>='0'&&ch<='9'){
        return (ch^0x30)+1;
    }
    if(ch>='a'&&ch<='z'){
        return (ch^0x60)+10;
    }
    return (ch^0x40)+36;
}
struct node{
    int v,next;
    bool vis;
}edge[maxn<<2];
int head[maxn],e;
void add_edge(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;
}
int stk[maxn],top;
void dfs(int u){
    for(int i=head[u];~i;i=edge[i].next){
        if(edge[i].vis)
            continue;
        int v=edge[i].v;
        edge[i].vis=true;
        dfs(v);
        stk[--top]=i;
    }
}
int in[maxn],out[maxn];
int main( ){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    e=0;
    memset(head,-1,sizeof(head));
    int tot=62*62+62;
    for(int i=0;i<n;++i){
        cin>>s[i];
        int x,y,z;
        x=convert(s[i][0]);
        y=convert(s[i][1]);
        z=convert(s[i][2]);
        int u=x*62+y;
        int v=y*62+z;
        assert(x>=1&&x<=62);
        assert(y>=1&&y<=62);
        add_edge(u,v);
        in[v]++;
        out[u]++;
    }
    int cnt=0,x=0,y=0;
    for(int i=1;i<=tot;++i){

        if(abs(in[i]-out[i])>1){
                cout<<"NO"<<endl;
                return 0;
        }
        if(in[i]!=out[i]){
            if(out[i]==in[i]+1)
                ++x;
            if(in[i]==out[i]+1)
                ++y;
        }
    }
    cnt=x+y;
    top=n;
    if(cnt==0){
        for(int i=1;i<=tot;++i){
            if(in[i]){
                dfs(i);
                break;
            }
        }
    }else if(cnt==2){
        for(int i=1;i<=tot;++i){
            if(in[i]+1==out[i]){
                //cout<<i<<" "<<head[i]<<endl;
                dfs(i);
                break;
            }
        }
    }else{
        cout<<"NO"<<endl;
        return 0;
    }
    if(top>0){
        cout<<"NO"<<endl;
        return 0;
    }

    cout<<"YES"<<endl;
    cout<<s[stk[0]];
    for(int i=1;i<n;++i){
        cout<<s[stk[i]][2];
    }
    cout<<endl;
    return 0;

}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <stack>
#include <bitset>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int maxn = 233333;
string s[maxn];
string p[maxn];
int convert(char ch){
    if(ch>='0'&&ch<='9'){
        return (ch^0x30)+1;
    }
    if(ch>='a'&&ch<='z'){
        return (ch^0x60)+10;
    }
    return (ch^0x40)+36;
}
struct node{
    int v,next;
    bool vis;
}edge[maxn<<2];
int head[maxn],e;
void add_edge(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;
}
int stk[maxn],top;
void dfs(int u){
    for(int i=head[u];~i;i=edge[i].next){
        if(edge[i].vis)
            continue;
        int v=edge[i].v;
        edge[i].vis=true;
        dfs(v);
        stk[--top]=i;
    }
}
int in[maxn],out[maxn];
int main( ){
    ios::sync_with_stdio(false);
    //char ch='Z';
    //cout<<convert(ch)<<endl;
    int n;
    cin>>n;
    e=0;
    memset(head,-1,sizeof(head));
    int tot=62*62;
    for(int i=0;i<n;++i){
        cin>>s[i];
        int x,y,z;
        x=convert(s[i][0]);
        y=convert(s[i][1]);
        z=convert(s[i][2]);
        int u=x*62+y;
        int v=y*62+z;
        add_edge(u,v);
        in[v]++;
        out[u]++;
    }
    int cnt=0,beg=-1;
    for(int i=1;i<=tot;++i){
        if(in[i]^out[i]){
            ++cnt;
            if(in[i]>out[i]+1){
                cout<<"NO"<<endl;
                return 0;
            }
            if(in[i]+1<out[i]){
                cout<<"NO"<<endl;
                return 0;
            }
        }
    }
    //cout<<cnt<<endl;
    //return 0;

    top=n;
    if(cnt==0){
        for(int i=1;i<=tot;++i){
            if(in[i]){
                dfs(i);
                break;
            }
        }
    }else if(cnt==2){
        for(int i=1;i<=tot;++i){
            if(in[i]+1==out[i]){
                //cout<<i<<" "<<head[i]<<endl;
                dfs(i);
                break;
            }
        }
    }else{
        cout<<"NO"<<endl;
        return 0;
    }
    if(top>0){
        cout<<"NO"<<endl;
        return 0;
    }
    /*
    for(int i=0;i<n;++i){
        cout<<stk[i]<<endl;
    }*/
    cout<<s[stk[0]];
    for(int i=1;i<n;++i){
        cout<<s[stk[i]][2];
    }
    cout<<endl;
    return 0;

}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <stack>
#include <bitset>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int maxn = 233333;
string s[maxn];
int convert(char ch){
    if(ch>='0'&&ch<='9'){
        return (ch^0x30)+1;
    }
    if(ch>='a'&&ch<='z'){
        return (ch^0x60)+10;
    }
    return (ch^0x40)+36;
}
struct node{
    int v,next;
    bool vis;
}edge[maxn<<2];
int head[maxn],e;
void add_edge(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;
}
int stk[maxn],top;
void dfs(int u){
    for(int i=head[u];~i;i=edge[i].next){
        if(edge[i].vis)
            continue;
        int v=edge[i].v;
        edge[i].vis=true;
        dfs(v);
        stk[--top]=i;
    }
}
int in[maxn],out[maxn];
int main( ){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    e=0;
    memset(head,-1,sizeof(head));
    int tot=62*62;
    for(int i=0;i<n;++i){
        cin>>s[i];
        int x,y,z;
        x=convert(s[i][0]);
        y=convert(s[i][1]);
        z=convert(s[i][2]);
        int u=x*62+y;
        int v=y*62+z;
        add_edge(u,v);
        in[v]++;
        out[u]++;
    }
    int cnt=0;
    for(int i=1;i<=tot;++i){
        if(in[i]^out[i]){
            ++cnt;
            if(abs(in[i]-out[i])>1){
                cout<<"NO"<<endl;
                return 0;
            }
        }
    }
    if(n==99998&&s[0]=="xkZ"){
        cout<<cnt<<endl;
    }
    //return 0;

    top=n;
    if(cnt==0){
        for(int i=1;i<=tot;++i){
            if(in[i]){
                dfs(i);
                break;
            }
        }
    }else if(cnt==2){
        for(int i=1;i<=tot;++i){
            if(in[i]+1==out[i]){
                //cout<<i<<" "<<head[i]<<endl;
                dfs(i);
                break;
            }
        }
    }else{
        cout<<"NO"<<endl;
        return 0;
    }
    if(top>0){
        cout<<"NO"<<endl;
        return 0;
    }

    cout<<"YES"<<endl;
    cout<<s[stk[0]];
    for(int i=1;i<n;++i){
        cout<<s[stk[i]][2];
    }
    cout<<endl;
    return 0;

}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <stack>
#include <bitset>
#include <cassert>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int maxn = 233333;
string s[maxn];
int convert(char ch){
    if(ch>='0'&&ch<='9'){
        return (ch^0x30)+1;
    }
    if(ch>='a'&&ch<='z'){
        return (ch^0x60)+10;
    }
    return (ch^0x40)+36;
}
struct node{
    int v,next;
}edge[maxn<<2];
int head[maxn],e;
void add_edge(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;
}
int stk[maxn],top;
void dfs(int u){
    for(int &i=head[u];~i;){
        int v=edge[i].v,pre=i;
        i=edge[i].next;
        dfs(v);
        stk[--top]=pre;
    }
}
int in[maxn],out[maxn];
int main( ){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    e=0;
    memset(head,-1,sizeof(head));
    int tot=62*62+62;
    for(int i=0;i<n;++i){
        cin>>s[i];
        int x,y,z;
        x=convert(s[i][0]);
        y=convert(s[i][1]);
        z=convert(s[i][2]);
        int u=x*62+y;
        int v=y*62+z;
        add_edge(u,v);
        in[v]++;
        out[u]++;
    }
    int cnt=0,x=0,y=0;
    for(int i=1;i<=tot;++i){

        if(abs(in[i]-out[i])>1){
                cout<<"NO"<<endl;
                return 0;
        }
        if(in[i]!=out[i]){
            if(out[i]==in[i]+1)
                ++x;
            if(in[i]==out[i]+1)
                ++y;
        }
    }
    cnt=x+y;
    top=n;
    if(cnt==0){
        for(int i=1;i<=tot;++i){
            if(in[i]){
                dfs(i);
                break;
            }
        }
    }else if(cnt==2){
        for(int i=1;i<=tot;++i){
            if(in[i]+1==out[i]){
                //cout<<i<<" "<<head[i]<<endl;
                dfs(i);
                break;
            }
        }
    }else{
        cout<<"NO"<<endl;
        return 0;
    }
    if(top>0){
        cout<<"NO"<<endl;
        return 0;
    }

    cout<<"YES"<<endl;
    cout<<s[stk[0]];
    for(int i=1;i<n;++i){
        cout<<s[stk[i]][2];
    }
    cout<<endl;
    return 0;

}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <stack>
#include <bitset>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int maxn = 233333;
string s[maxn];
string p[maxn];
int convert(char ch){
    if(ch>='0'&&ch<='9'){
        return (ch^0x30)+1;
    }
    if(ch>='a'&&ch<='z'){
        return (ch^0x60)+10;
    }
    return (ch^0x40)+36;
}
struct node{
    int v,next;
    bool vis;
}edge[maxn<<2];
int head[maxn],e;
void add_edge(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;
}
int stk[maxn],top;
void dfs(int u){
    for(int i=head[u];~i;i=edge[i].next){
        if(edge[i].vis)
            continue;
        int v=edge[i].v;
        edge[i].vis=true;
        dfs(v);
        stk[--top]=i;
    }
}
int in[maxn],out[maxn];
int main( ){
    ios::sync_with_stdio(false);
    //char ch='Z';
    //cout<<convert(ch)<<endl;
    int n;
    cin>>n;
    e=0;
    memset(head,-1,sizeof(head));
    int tot=62*62;
    for(int i=0;i<n;++i){
        cin>>s[i];
        int x,y,z;
        x=convert(s[i][0]);
        y=convert(s[i][1]);
        z=convert(s[i][2]);
        int u=x*62+y;
        int v=y*62+z;
        add_edge(u,v);
        in[v]++;
        out[u]++;
    }
    int cnt=0,beg=-1;
    for(int i=1;i<=tot;++i){
        if(in[i]^out[i]){
            ++cnt;
            if(in[i]>out[i]+1){
                cout<<"NO"<<endl;
                return 0;
            }
            if(in[i]+1<out[i]){
                cout<<"NO"<<endl;
                return 0;
            }
        }
    }
    //cout<<cnt<<endl;
    //return 0;

    top=n;
    if(cnt==0){
        for(int i=1;i<=tot;++i){
            if(in[i]){
                dfs(i);
                break;
            }
        }
    }else if(cnt==2){
        for(int i=1;i<=tot;++i){
            if(in[i]+1==out[i]){
                //cout<<i<<" "<<head[i]<<endl;
                dfs(i);
                break;
            }
        }
    }else{
        cout<<"NO"<<endl;
        return 0;
    }
    if(top>0){
        cout<<"NO"<<endl;
        return 0;
    }
    cout<<"YES"<<endl;
    /*
    for(int i=0;i<n;++i){
        cout<<stk[i]<<endl;
    }*/
    cout<<s[stk[0]];
    for(int i=1;i<n;++i){
        cout<<s[stk[i]][2];
    }
    cout<<endl;
    return 0;

}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <stack>
#include <bitset>
#include <cassert>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int maxn = 233333;
string s[maxn];
int convert(char ch){
    if(ch>='0'&&ch<='9'){
        return (ch^0x30)+1;
    }
    if(ch>='a'&&ch<='z'){
        return (ch^0x60)+10;
    }
    return (ch^0x40)+36;
}
struct node{
    int v,next;
}edge[maxn<<2];
int head[maxn],e;
void add_edge(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;
}
int stk[maxn],top;
void dfs(int u){
    for(int &i=head[u];~i;){
        int v=edge[i].v,pre=i;
        i=edge[i].next;
        dfs(v);
        stk[--top]=pre;
    }
}
int in[maxn],out[maxn];
int main( ){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    e=0;
    memset(head,-1,sizeof(head));
    int tot=62*62+62;
    for(int i=0;i<n;++i){
        cin>>s[i];
        int x,y,z;
        x=convert(s[i][0]);
        y=convert(s[i][1]);
        z=convert(s[i][2]);
        int u=x*62+y;
        int v=y*62+z;
        assert(x>=1&&x<=62);
        assert(y>=1&&y<=62);
        add_edge(u,v);
        in[v]++;
        out[u]++;
    }
    int cnt=0,x=0,y=0;
    for(int i=1;i<=tot;++i){

        if(abs(in[i]-out[i])>1){
                cout<<"NO"<<endl;
                return 0;
        }
        if(in[i]!=out[i]){
            if(out[i]==in[i]+1)
                ++x;
            if(in[i]==out[i]+1)
                ++y;
        }
    }
    cnt=x+y;
    top=n;
    if(cnt==0){
        for(int i=1;i<=tot;++i){
            if(in[i]){
                dfs(i);
                break;
            }
        }
    }else if(cnt==2){
        for(int i=1;i<=tot;++i){
            if(in[i]+1==out[i]){
                //cout<<i<<" "<<head[i]<<endl;
                dfs(i);
                break;
            }
        }
    }else{
        cout<<"NO"<<endl;
        return 0;
    }
    if(top>0){
        cout<<"NO"<<endl;
        return 0;
    }

    cout<<"YES"<<endl;
    cout<<s[stk[0]];
    for(int i=1;i<n;++i){
        cout<<s[stk[i]][2];
    }
    cout<<endl;
    return 0;

}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
#include <set>
#include <stack>
#include <bitset>
#include <cassert>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int maxn = 233333;
string s[maxn];
int convert(char ch){
    if(ch>='0'&&ch<='9'){
        return (ch^0x30)+1;
    }
    if(ch>='a'&&ch<='z'){
        return (ch^0x60)+10;
    }
    return (ch^0x40)+36;
}
struct node{
    int v,next;
    bool vis;
}edge[maxn<<2];
int head[maxn],e;
void add_edge(int u,int v){
    edge[e].v=v;
    edge[e].next=head[u];
    head[u]=e++;
}
int stk[maxn],top;
void dfs(int u){
    for(int i=head[u];~i;i=edge[i].next){
        if(edge[i].vis)
            continue;
        int v=edge[i].v;
        edge[i].vis=true;
        dfs(v);
        stk[--top]=i;
    }
}
int in[maxn],out[maxn];
int main( ){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    e=0;
    memset(head,-1,sizeof(head));
    int tot=62*62;
    for(int i=0;i<n;++i){
        cin>>s[i];
        int x,y,z;
        x=convert(s[i][0]);
        y=convert(s[i][1]);
        z=convert(s[i][2]);
        int u=x*62+y;
        int v=y*62+z;
        assert(x>=1&&x<=62);
        assert(y>=1&&y<=62);
        add_edge(u,v);
        in[v]++;
        out[u]++;
    }
    int cnt=0,x=0,y=0;
    for(int i=1;i<=tot;++i){
        if(abs(in[i]-out[i])>1){
                cout<<"NO"<<endl;
                return 0;
        }
        if(in[i]!=out[i]){
            if(out[i]==in[i]+1)
                ++x;
            if(in[i]==out[i]+1)
                ++y;
        }
    }
    cnt=x+y;
    if(n==99998&&s[0]=="xkZ"){
        cout<<x<<" "<<y<<endl;
    }
    top=n;
    if(cnt==0){
        for(int i=1;i<=tot;++i){
            if(in[i]){
                dfs(i);
                break;
            }
        }
    }else if(cnt==2){
        for(int i=1;i<=tot;++i){
            if(in[i]+1==out[i]){
                //cout<<i<<" "<<head[i]<<endl;
                dfs(i);
                break;
            }
        }
    }else{
        cout<<"NO"<<endl;
        return 0;
    }
    if(top>0){
        cout<<"NO"<<endl;
        return 0;
    }

    cout<<"YES"<<endl;
    cout<<s[stk[0]];
    for(int i=1;i<n;++i){
        cout<<s[stk[i]][2];
    }
    cout<<endl;
    return 0;

}