# include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair < ll, ll > pll;
typedef pair < int, int > pii;

const ll maxN = ll(8e5);
const ll smaxN = ll(5e3);
const ll mmaxN = ll(3e4);
const ll lmaxN = ll(3e6);
const ll oo = ll(1e18);
const ll MOD = ll(1e9) + 7;
const ld EPS = 1e-10;
const ld PI = acos(0.0) * 2;
const ll dx[] = {-1, +0, +0, +1};
const ll dy[] = {+0, -1, +1, +0};

template<typename T>
T Sqr(T x) {
    return x * x;
}

template<class T>
ll Sz(T x) {
    return ll(x.size());
}

inline ll MultMod(ll a, ll b, ll mod) {
    if(b < 0)
        return (a * b) % mod;
    if(b == 0)
        return 0;
    if(b % 2)
        return (MultMod(a, b - 1, mod) + a) % mod;
    return (MultMod(a, b / 2, mod) * 2) % mod;
}

inline ll ModPow(ll a, ll b, ll mod){
    if(b == 0)
        return 1ll % mod;
    if(b == 1)
        return a % mod;
    if(b % 2)
        return MultMod(ModPow(a, b - 1, mod), a, mod) % mod;
    ll z = ModPow(a, b / 2, mod);
    return (MultMod(z, z, mod)) % mod;
}

void compress(vector < ll > &a){
    vector < ll > b(a);
    sort(b.begin(), b.end());
    b.erase(unique(b.begin(), b.end()), b.end());
    for(auto &i : a) i = lower_bound(b.begin(), b.end(), i) - b.begin() + 1;
}

inline bool Palindrome(const string &s){
    return equal(s.begin(), s.end(), s.rbegin());
}

inline bool Prime(ll x){
    if(x < 2)
        return 0;
    for(ll i = 2; i * i <= x; ++i)
        if(x % i == 0)
            return 0;
    return 1;
}

inline bool IsProbablePrime(ll x){
    return 1; // -> returns 1
}

ll BLOCK;

struct Query{
    ll l, r, id;
    Query(){}

    Query(ll l, ll r, ll id) : l(l), r(r), id(id){}

    bool operator < (Query b) const{
        return (this -> l / BLOCK != b.l / BLOCK ? this -> l / BLOCK < b.l / BLOCK : this -> r < b.r);
    }

    ~Query(){}
};

ll n, m, k, l, r, now;
ll pref[lmaxN], cnt[lmaxN], res[lmaxN];
vector < Query > v;

void Add(ll val){
    now += cnt[val ^ k];
    ++cnt[val];
}

void Del(ll val){
    --cnt[val];
    now -= cnt[val ^ k];
}

main(){
    scanf("%lld %lld %lld", &n, &m, &k);
    BLOCK = (ll)sqrt(n + .0) + 1;
    for(ll i = 1; i <= n; ++i)
        scanf("%lld", &pref[i]), pref[i] ^= pref[i - 1];
    for(ll i = 1; i <= m; ++i){
        scanf("%lld %lld", &l, &r);
        --l;
        v.push_back(Query(l, r, i));
    }
    sort(v.begin(), v.end());
    ll L = v[0].l, R = v[0].r;
    for(ll i = L; i <= R; ++i) Add(pref[i]);
    res[v[0].id] = now;
    for(ll c = 1; c < Sz(v); ++c){
        while(l < v[c].l)
            Del(pref[l]), ++l;
        while(l > v[c].l)
            Add(pref[l - 1]), --l;
        while(r > v[c].r)
            Del(pref[r]), --r;
        while(r < v[c].r)
            Add(pref[r + 1]), ++r;
        res[v[c].id] = now;
    }
    for(ll i = 1; i <= m; ++i)
        printf("%lld\n", res[i]);
    return 0;
}


# include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair < ll, ll > pll;
typedef pair < int, int > pii;

const ll maxN = ll(8e5);
const ll smaxN = ll(5e3);
const ll mmaxN = ll(3e4);
const ll lmaxN = ll(3e6);
const ll oo = ll(1e18);
const ll MOD = ll(1e9) + 7;
const ld EPS = 1e-10;
const ld PI = acos(0.0) * 2;
const ll dx[] = {-1, +0, +0, +1};
const ll dy[] = {+0, -1, +1, +0};

template<typename T>
T Sqr(T x) {
    return x * x;
}

template<class T>
ll Sz(T x) {
    return ll(x.size());
}

inline ll MultMod(ll a, ll b, ll mod) {
    if(b < 0)
        return (a * b) % mod;
    if(b == 0)
        return 0;
    if(b % 2)
        return (MultMod(a, b - 1, mod) + a) % mod;
    return (MultMod(a, b / 2, mod) * 2) % mod;
}

inline ll ModPow(ll a, ll b, ll mod){
    if(b == 0)
        return 1ll % mod;
    if(b == 1)
        return a % mod;
    if(b % 2)
        return MultMod(ModPow(a, b - 1, mod), a, mod) % mod;
    ll z = ModPow(a, b / 2, mod);
    return (MultMod(z, z, mod)) % mod;
}

void compress(vector < ll > &a){
    vector < ll > b(a);
    sort(b.begin(), b.end());
    b.erase(unique(b.begin(), b.end()), b.end());
    for(auto &i : a) i = lower_bound(b.begin(), b.end(), i) - b.begin() + 1;
}

inline bool Palindrome(const string &s){
    return equal(s.begin(), s.end(), s.rbegin());
}

inline bool Prime(ll x){
    if(x < 2)
        return 0;
    for(ll i = 2; i * i <= x; ++i)
        if(x % i == 0)
            return 0;
    return 1;
}

inline bool IsProbablePrime(ll x){
    return 1; // -> returns 1
}

ll BLOCK = 317;

struct Query{
    ll l, r, id;
    Query(){}

    Query(ll l, ll r, ll id) : l(l), r(r), id(id){}

    bool operator < (Query b) const{
        if(l / BLOCK != b.l / BLOCK)
            return l / BLOCK < b.l / BLOCK;
        return r < b.r;
    }

    ~Query(){}
};

ll n, m, k, l, r, now;
ll pref[lmaxN], cnt[lmaxN], res[lmaxN];
Query v[maxN];

void Add(ll val){
    now += cnt[val ^ k];
    ++cnt[val];
}

void Del(ll val){
    --cnt[val];
    now -= cnt[val ^ k];
}

main(){
    scanf("%I64d %I64d %I64d", &n, &m, &k);
    for(ll i = 1; i <= n; ++i)
        scanf("%I64d", &pref[i]), pref[i] ^= pref[i - 1];
    for(ll i = 1; i <= m; ++i){
        scanf("%I64d %I64d", &l, &r);
        --l;
        v[i] = Query(l, r, i);
    }
    sort(v + 1, v + 1 + m);
    ll L = v[1].l, R = v[1].r;
    for(ll i = L; i <= R; ++i) Add(pref[i]);
    res[v[1].id] = now;
    for(ll c = 2; c <= m; ++c){
        while(L < v[c].l)
            Del(pref[L]), ++L;
        while(L > v[c].l)
            Add(pref[L - 1]), --L;
        while(R > v[c].r)
            Del(pref[R]), --R;
        while(R < v[c].r)
            Add(pref[R + 1]), ++R;
        res[v[c].id] = now;
    }
    for(ll i = 1; i <= m; ++i)
        printf("%I64d\n", res[i]);
    return 0;
}


 # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair < ll, ll > pll;
typedef pair < int, int > pii;

const ll maxN = ll(8e5);
const ll smaxN = ll(5e3);
const ll mmaxN = ll(3e4);
const ll lmaxN = ll(3e6);
const ll oo = ll(1e18);
const ll MOD = ll(1e9) + 7;
const ld EPS = 1e-10;
const ld PI = acos(0.0) * 2;
const ll dx[] = {-1, +0, +0, +1};
const ll dy[] = {+0, -1, +1, +0};

template<typename T>
T Sqr(T x) {
    return x * x;
}

template<class T>
ll Sz(T x) {
    return ll(x.size());
}

inline ll MultMod(ll a, ll b, ll mod) {
    if(b < 0)
        return (a * b) % mod;
    if(b == 0)
        return 0;
    if(b % 2)
        return (MultMod(a, b - 1, mod) + a) % mod;
    return (MultMod(a, b / 2, mod) * 2) % mod;
}

inline ll ModPow(ll a, ll b, ll mod){
    if(b == 0)
        return 1ll % mod;
    if(b == 1)
        return a % mod;
    if(b % 2)
        return MultMod(ModPow(a, b - 1, mod), a, mod) % mod;
    ll z = ModPow(a, b / 2, mod);
    return (MultMod(z, z, mod)) % mod;
}

void compress(vector < ll > &a){
    vector < ll > b(a);
    sort(b.begin(), b.end());
    b.erase(unique(b.begin(), b.end()), b.end());
    for(auto &i : a) i = lower_bound(b.begin(), b.end(), i) - b.begin() + 1;
}

inline bool Palindrome(const string &s){
    return equal(s.begin(), s.end(), s.rbegin());
}

inline bool Prime(ll x){
    if(x < 2)
        return 0;
    for(ll i = 2; i * i <= x; ++i)
        if(x % i == 0)
            return 0;
    return 1;
}

inline bool IsProbablePrime(ll x){
    return 1; // -> returns 1
}

ll BLOCK = 317;

struct Query{
    ll l, r, id;
    Query(){}

    Query(ll l, ll r, ll id) : l(l), r(r), id(id){}

    bool operator < (Query b) const{
        ll lb = this -> l / BLOCK, rb = b.l / BLOCK;
        if(lb != rb)
            return lb < rb;
        return this -> r > b.r;
    }

    ~Query(){}
};

ll n, m, k, l, r, now;
ll pref[lmaxN], cnt[lmaxN], res[lmaxN];
vector < Query > v;

void Add(ll val){
    now += cnt[val ^ k];
    ++cnt[val];

}

void Del(ll val){
    now -= cnt[val ^ k];
    --cnt[val];
}

main(){
    scanf("%I64d %I64d %I64d", &n, &m, &k);
    for(ll i = 1; i <= n; ++i)
        scanf("%I64d", &pref[i]), pref[i] ^= pref[i - 1];
    for(ll i = 1; i <= m; ++i){
        scanf("%I64d %I64d", &l, &r);
        --l;
        v.push_back(Query(l, r, i));
    }
    sort(v.begin(), v.end());
    ll L = v[0].l, R = v[0].r;
    for(ll i = L; i <= R; ++i) Add(pref[i]);
    res[v[0].id] = now;
    for(ll c = 1; c < Sz(v); ++c){
        while(L < v[c].l)
            Del(pref[L]), ++L;
        while(L > v[c].l)
            Add(pref[L - 1]), --L;
        while(R > v[c].r)
            Del(pref[R]), --R;
        while(R < v[c].r)
            Add(pref[R + 1]), ++R;
        res[v[c].id] = now;
    }
    for(ll i = 1; i <= m; ++i)
        printf("%I64d\n", res[i]);
    return 0;
}


 # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair < ll, ll > pll;
typedef pair < int, int > pii;

const ll maxN = ll(8e5);
const ll smaxN = ll(5e3);
const ll mmaxN = ll(3e4);
const ll lmaxN = ll(3e6);
const ll oo = ll(1e18);
const ll MOD = ll(1e9) + 7;
const ld EPS = 1e-10;
const ld PI = acos(0.0) * 2;
const ll dx[] = {-1, +0, +0, +1};
const ll dy[] = {+0, -1, +1, +0};

template<typename T>
T Sqr(T x) {
    return x * x;
}

template<class T>
ll Sz(T x) {
    return ll(x.size());
}

inline ll MultMod(ll a, ll b, ll mod) {
    if(b < 0)
        return (a * b) % mod;
    if(b == 0)
        return 0;
    if(b % 2)
        return (MultMod(a, b - 1, mod) + a) % mod;
    return (MultMod(a, b / 2, mod) * 2) % mod;
}

inline ll ModPow(ll a, ll b, ll mod){
    if(b == 0)
        return 1ll % mod;
    if(b == 1)
        return a % mod;
    if(b % 2)
        return MultMod(ModPow(a, b - 1, mod), a, mod) % mod;
    ll z = ModPow(a, b / 2, mod);
    return (MultMod(z, z, mod)) % mod;
}

void compress(vector < ll > &a){
    vector < ll > b(a);
    sort(b.begin(), b.end());
    b.erase(unique(b.begin(), b.end()), b.end());
    for(auto &i : a) i = lower_bound(b.begin(), b.end(), i) - b.begin() + 1;
}

inline bool Palindrome(const string &s){
    return equal(s.begin(), s.end(), s.rbegin());
}

inline bool Prime(ll x){
    if(x < 2)
        return 0;
    for(ll i = 2; i * i <= x; ++i)
        if(x % i == 0)
            return 0;
    return 1;
}

inline bool IsProbablePrime(ll x){
    return 1; // -> returns 1
}

ll BLOCK;

struct Query{
    ll l, r, id;
    Query(){}

    Query(ll l, ll r, ll id) : l(l), r(r), id(id){}

    bool operator < (Query &b) const{
        ll lb = this -> l / BLOCK, rb = b.l / BLOCK;
        if(lb != rb)
            return lb < rb;
        return this -> r > b.r;
    }

    ~Query(){}
};

ll n, m, k, l, r, now;
ll pref[lmaxN], cnt[lmaxN], res[lmaxN];
vector < Query > v;

void Add(ll val){
    ++cnt[val];
    now += cnt[val ^ k];
}

void Del(ll val){
    now -= cnt[val ^ k];
    --cnt[val];
}

main(){
    scanf("%lld %lld %lld", &n, &m, &k);
    BLOCK = (ll)sqrt(n + .0) + 1;
    for(ll i = 1; i <= n; ++i)
        scanf("%lld", &pref[i]), pref[i] ^= pref[i - 1];
    for(ll i = 1; i <= m; ++i){
        scanf("%lld %lld", &l, &r);
        --l;
        v.push_back(Query(l, r, i));
    }
    sort(v.begin(), v.end());
    ll L = v[0].l, R = v[0].r;
    for(ll i = L; i <= R; ++i) Add(pref[i]);
    res[v[0].id] = now;
    for(ll c = 1; c < Sz(v); ++c){
        while(L < v[c].l)
            Del(pref[L]), ++L;
        while(L > v[c].l)
            Add(pref[L - 1]), --L;
        while(R > v[c].r)
            Del(pref[R]), --R;
        while(R < v[c].r)
            Add(pref[R + 1]), ++R;
        res[v[c].id] = now;
    }
    for(ll i = 1; i <= m; ++i)
        printf("%lld\n", res[i]);
    return 0;
}


# include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair < ll, ll > pll;
typedef pair < int, int > pii;

const ll maxN = ll(8e5);
const ll smaxN = ll(5e3);
const ll mmaxN = ll(3e4);
const ll lmaxN = ll(3e6);
const ll oo = ll(1e18);
const ll MOD = ll(1e9) + 7;
const ld EPS = 1e-10;
const ld PI = acos(0.0) * 2;
const ll dx[] = {-1, +0, +0, +1};
const ll dy[] = {+0, -1, +1, +0};

template<typename T>
T Sqr(T x) {
    return x * x;
}

template<class T>
ll Sz(T x) {
    return ll(x.size());
}

inline ll MultMod(ll a, ll b, ll mod) {
    if(b < 0)
        return (a * b) % mod;
    if(b == 0)
        return 0;
    if(b % 2)
        return (MultMod(a, b - 1, mod) + a) % mod;
    return (MultMod(a, b / 2, mod) * 2) % mod;
}

inline ll ModPow(ll a, ll b, ll mod){
    if(b == 0)
        return 1ll % mod;
    if(b == 1)
        return a % mod;
    if(b % 2)
        return MultMod(ModPow(a, b - 1, mod), a, mod) % mod;
    ll z = ModPow(a, b / 2, mod);
    return (MultMod(z, z, mod)) % mod;
}

void compress(vector < ll > &a){
    vector < ll > b(a);
    sort(b.begin(), b.end());
    b.erase(unique(b.begin(), b.end()), b.end());
    for(auto &i : a) i = lower_bound(b.begin(), b.end(), i) - b.begin() + 1;
}

inline bool Palindrome(const string &s){
    return equal(s.begin(), s.end(), s.rbegin());
}

inline bool Prime(ll x){
    if(x < 2)
        return 0;
    for(ll i = 2; i * i <= x; ++i)
        if(x % i == 0)
            return 0;
    return 1;
}

inline bool IsProbablePrime(ll x){
    return 1; // -> returns 1
}

ll BLOCK;

struct Query{
    ll l, r, id;
    Query(){}

    Query(ll l, ll r, ll id) : l(l), r(r), id(id){}

    bool operator < (Query b) const{
        return (this -> l / BLOCK != b.l / BLOCK ? this -> l / BLOCK < b.l / BLOCK : this -> r < b.r);
    }

    ~Query(){}
};

ll n, m, k, l, r, now;
ll pref[lmaxN], cnt[lmaxN], res[lmaxN];
vector < Query > v;

void Add(ll val){
    ++cnt[val];
    now += cnt[val ^ k];
}

void Del(ll val){
    now -= cnt[val ^ k];
    --cnt[val];
}

main(){
    scanf("%lld %lld %lld", &n, &m, &k);
    BLOCK = (ll)sqrt(n + .0) + 1;
    for(ll i = 1; i <= n; ++i)
        scanf("%lld", &pref[i]), pref[i] ^= pref[i - 1];
    for(ll i = 1; i <= m; ++i){
        scanf("%lld %lld", &l, &r);
        --l;
        v.push_back(Query(l, r, i));
    }
    sort(v.begin(), v.end());
    ll L = v[0].l, R = v[0].r;
    for(ll i = L; i <= R; ++i) Add(pref[i]);
    res[v[0].id] = now;
    for(ll c = 1; c < Sz(v); ++c){
        while(l < v[c].l)
            Del(pref[l]), ++l;
        while(l > v[c].l)
            Add(pref[l - 1]), --l;
        while(r > v[c].r)
            Del(pref[r]), --r;
        while(r < v[c].r)
            Add(pref[r + 1]), ++r;
        res[v[c].id] = now;
    }
    for(ll i = 1; i <= m; ++i)
        printf("%lld\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1 << 20;
int n, m, k, a[maxn]
int len;
ll ans = 0, res[maxn], vis[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id) {
        block = l / len;
    }

    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    ans += vis[a[pos] ^ k];
    vis[a[pos]]++;
}
void Erase(int pos)
{
    ans -= vis[a[pos] ^ k];
    vis[a[pos]]--;
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1050000;
int res[maxn], ans = 0;
int n, m, k, a[maxn];
int len, vis[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    vis[a[pos]]++;
    ans += vis[a[pos] ^ k];
}
void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}
int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1 << 20;
int n, m, k, a[maxn];
int len;
ll ans = 0, res[maxn], vis[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id) {
        block = l / len;
    }

    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    ans += vis[a[pos] ^ k];
    vis[a[pos]]++;
}
void Erase(int pos)
{
    ans -= vis[a[pos] ^ k];
    vis[a[pos]]--;
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 5;
int res[maxn];
int n, m, k, a[maxn];
int len;
ll ans = 0, vis[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id) {
        block = l / len;
    }

    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    vis[a[pos]]++;
    ans += vis[a[pos] ^ k];
}
void Erase(int pos)
{
    ans -= vis[a[pos] ^ k];
    vis[a[pos]]--;
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
const int Max = 1e6 + 5;
ll res[maxn];
int n, m, k;
ll a[maxn], ans = 0;
int len, vis[Max];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    vis[a[pos]]++;
    ans += vis[a[pos] ^ k];
}
void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}
int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%I64d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%I64d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 5;
ll ans = 0, res[maxn], vis[maxn];
int n, m, k, len;
int a[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
}q[maxn];

void Insert(int pos)
{
    ans += vis[a[pos] ^ k];
    vis[a[pos]]++;
}

void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }

    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);

        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1 << 20;

int n, m, k, len;
int a[maxn];
ll ans = 0, flag[maxn], res[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
}q[maxn];

void add(int pos)
{
    ans += flag[a[pos] ^ k];
    flag[a[pos]]++;
}
void del(int pos)
{
    flag[a[pos]]--;
    ans -= flag[a[pos] ^ k];
}
int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);

    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }

    int L, R;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &L, &R);
        q[i] = node(L, R, i);
    }

    sort(q + 1, q + 1 + m);
    L = 1, R = 0, flag[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r) add(++R);
        while(L > q[i].l) L--, add(L - 1);
        while(L < q[i].l) del(L - 1), L++;
        while(R > q[i].r) del(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++) {
        printf("%I64d\n", res[i]);
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 5;
ll ans = 0, res[maxn], vis[maxn];
int n, m, k, len;
int a[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
}q[maxn];

void Insert(int pos)
{
    ans += vis[a[pos] ^ k];
    vis[a[pos]]++;
}

void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }

    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);

        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%I64d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1 << 20;
ll ans = 0, res[maxn], vis[maxn];
int n, m, k, len;
int a[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
}q[maxn];

void Insert(int pos)
{
    ans += vis[a[pos] ^ k];
    vis[a[pos]]++;
}

void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }

    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);

        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%I64d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
const int Max = 1e6 + 5;
int res[maxn], ans = 0;
int n, m, k, a[maxn];
int len, vis[Max];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    vis[a[pos]]++;
    ans += vis[a[pos] ^ k];
}
void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}
int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
        printf("%d ", a[i]);
    }
    puts("");
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 5;
ll ans = 0, res[maxn], vis[maxn];
int n, m, k, len;
int a[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
}q[maxn];

void Insert(int pos)
{
    vis[a[pos]]++;
    ans += vis[a[pos] ^ k];
}

void Erase(int pos)
{
    ans -= vis[a[pos] ^ k];
    vis[a[pos]]--;
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }

    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);

        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
const int Max = 1e6 + 5;
int res[maxn], ans = 0;
int n, m, k, a[maxn];
int len, vis[Max];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    vis[a[pos]]++;
    ans += vis[a[pos] ^ k];
}
void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}
int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
//        printf("%d ", a[i]);
    }
//    puts("");
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
const int Max = 1e6 + 5;
int res[maxn], ans = 0;
int n, m, k, a[maxn];
int len, vis[Max];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    vis[a[pos]]++;
    ans += vis[a[pos] ^ k];
}
void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}
int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
//        printf("%d ", a[i]);
    }
    puts("");
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 5;
int res[maxn], ans = 0;
int n, m, k, a[maxn];
int len, vis[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id)
    {
        block = l / len;
    }
    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    vis[a[pos]]++;
    ans += vis[a[pos] ^ k];
}
void Erase(int pos)
{
    vis[a[pos]]--;
    ans -= vis[a[pos] ^ k];
}
int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%d\n", res[i]);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1 << 20;
int n, m, k, a[maxn];
int len;
ll ans = 0, res[maxn], vis[maxn];
struct node
{
    int l, r, id, block;
    node() {}
    node(int l, int r, int id) : l(l), r(r), id(id) {
        block = l / len;
    }

    bool operator < (const node &b) const
    {
        if(block == b.block)
            return r < b.r;
        return block < b.block;
    }
} q[maxn];
void Insert(int pos)
{
    ans += vis[a[pos] ^ k];
    vis[a[pos]]++;
}

void Erase(int pos)
{
    ans -= vis[a[pos] ^ k];
    vis[a[pos]]--;
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    len = sqrt(n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        a[i] ^= a[i-1];
    }
    int l, r;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d", &l, &r);
        q[i] = node(l, r, i);
    }
    sort(q + 1, q + m + 1);
    int L = 1, R = 0;
    vis[0] = 1;
    for(int i = 1; i <= m; i++)
    {
        while(R < q[i].r)   Insert(++R);
        while(L > q[i].l)   L--, Insert(L - 1);
        while(L < q[i].l)   Erase(L - 1), L++;
        while(R > q[i].r)   Erase(R--);
        res[q[i].id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%I64d\n", res[i]);
    return 0;
}


#include<bits/stdtr1c++.h>
using namespace std;

vector<string> str;
map<string,int> idx;
typedef pair<int,int>pr;
vector<vector<pr > >v;
int d[50*50];
int c;
int vis[300009];
int en;
string ret;
stack<int> q;
void euler(int a)
{

	for(int i=0;i<v[a].size();i++)
	{
		if(vis[v[a][i].second])
			continue;
		vis[v[a][i].second]=1;
		euler(v[a][i].first);
		q.push(v[a][i].second);

	}

}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("2.in","r",stdin);

    #endif // ONLINE_JUDGE

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int n;

    cin>>n;
    string s;
    c=0;
    for(int i=0;i<n;i++)
    {
    	cin>>s;
    	str.push_back(s);
    	string a=s.substr(0,2);
    	string b=s.substr(1,2);
    	if(idx.count(a)==0)
    	    		idx[a]=c++;
    	if(idx.count(b)==0)
    	    		idx[b]=c++;

    	d[idx[a]]++;
    	d[idx[b]]--;
    }

    v.resize(c+2);
    for(int i=0;i<n;i++)
    {
    	string a=str[i].substr(0,2);
    	string b=str[i].substr(1,2);
    	//cout<<a<<" "<<b<<" "<<str[i]<<endl;
    	v[idx[a]].push_back(pr(idx[b],i));
    }
    int k=0;
    int st=0;

    for(int i=0;i<c;i++)
    {
    	int a=d[i];
    	if(a==1 || a==-1)
    	{
    		k++;
    		if(d[i]>0)
    			st=i;
    		else
    			en=i;
    	}
    	else if(a!=0)
    	{
    		k=4;
    	}
    }

    if(k==0 || k==2)
    {
    	ret="";

    	euler(st);
    	//reverse(q.begin(),q.end());
		ret+=str[q.top()];q.pop();
		//cout<<ret<<endl;
		while(q.size())
		{
			//cout<<str[q.top()]<<endl;
			ret+=str[q.top()].substr(2,1);
			q.pop();
		}
    	cout<<"YES\n"<<ret<<endl;
    }
    else
    	cout<<"NO\n";

    return 0;

}


#include<bits/stdtr1c++.h>
using namespace std;

vector<string> str;
map<string, int> idx;
typedef pair<int, int> pr;
vector<queue<pr> > v;
int d[70 * 70];
int c;
bool vis[200009];
int en;
string ret;
stack<int> q;
void euler(int a) {

		while (v[a].size()) {
			pr t=v[a].front();
			v[a].pop();
			if (vis[t.second])
				continue;
			vis[t.second] = 1;
			euler(t.first);
			q.push(t.second);
	}

}
int main() {

#ifndef ONLINE_JUDGE
	freopen("2.in", "r", stdin);

#endif // ONLINE_JUDGE
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int n;

	cin >> n;

	string s;

	c = 0;
	for (int i = 0; i < n; i++) {
		cin >> s;
		str.push_back(s);
		string a = s.substr(0, 2);
		string b = s.substr(1, 2);
		if (idx.count(a) == 0)
			idx[a] = c++;
		if (idx.count(b) == 0)
			idx[b] = c++;

		d[idx[a]]++;
		d[idx[b]]--;
	}
	v.resize(c + 2);
	for (int i = 0; i < n; i++) {
		string a = str[i].substr(0, 2);
		string b = str[i].substr(1, 2);
		v[idx[a]].push(pr(idx[b], i));
	}
	int k = 0;
	int st = 0;

	for (int i = 0; i < c; i++) {
		int a = d[i];
		if (a == 1 || a == -1) {
			k++;
			if (d[i] > 0)
				st = i;
			else
				en = i;
		} else if (a != 0) {
			k = 4;
		}
	}

	if (k == 0 || k == 2) {
		ret = "";
		euler(st);
		ret += str[q.top()];
		q.pop();
		while (q.size()) {
			ret += str[q.top()].substr(2, 1);
			q.pop();
		}
		if (ret.size() == n + 2)
			cout << "YES\n" << ret << endl;
		else
			cout << "NO\n";
	} else
		cout << "NO\n";

	return 0;

}


#include<bits/stdtr1c++.h>
using namespace std;

vector<string> str;
map<string, int> idx;
typedef pair<int, int> pr;
vector<queue<pr> > v;
int d[70 * 70];
int c;
string ret;
stack<int> q;
void euler(int a) {
	while (v[a].size()) {
		pr t=v[a].front();
		v[a].pop();
		euler(t.first);
		q.push(t.second);
}

}
int main() {

#ifndef ONLINE_JUDGE
	freopen("2.in", "r", stdin);

#endif // ONLINE_JUDGE
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int n;

	cin >> n;

	string s;

	c = 0;
	for (int i = 0; i < n; i++) {
		cin >> s;
		str.push_back(s);
		string a = s.substr(0, 2);
		string b = s.substr(1, 2);
		if (idx.count(a) == 0)
			idx[a] = c++;
		if (idx.count(b) == 0)
			idx[b] = c++;

		d[idx[a]]++;
		d[idx[b]]--;
	}
	v.resize(c + 2);
	for (int i = 0; i < n; i++) {
		string a = str[i].substr(0, 2);
		string b = str[i].substr(1, 2);
		v[idx[a]].push(pr(idx[b], i));
	}
	int k = 0;
	int st = 0;

	for (int i = 0; i < c; i++) {
		int a = d[i];
		if (a == 1 || a == -1) {
			k++;
			if (d[i] > 0)
				st = i;
		} else if (a != 0) {
			k = 4;
		}
	}

	if (k == 0 || k == 2) {
		ret = "";
		euler(st);
		ret += str[q.top()];
		q.pop();
		while (q.size()) {
			ret += str[q.top()].substr(2, 1);
			q.pop();
		}
		if (ret.size() == n + 2)
			cout << "YES\n" << ret << endl;
		else
			cout << "NO\n";
	} else
		cout << "NO\n";

	return 0;

}


#include<bits/stdtr1c++.h>
using namespace std;

vector<string> str;
map<string,int> idx;
typedef pair<int,int>pr;
vector<vector<pr > >v;
int d[70*70];
int c;
int vis[300009];
int en;
string ret;
stack<int> q;
void euler(int a)
{

	for(int i=0;i<v[a].size();i++)
	{
		if(vis[v[a][i].second])
			continue;
		vis[v[a][i].second]=1;
		euler(v[a][i].first);
		q.push(v[a][i].second);

	}

}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("2.in","r",stdin);

    #endif // ONLINE_JUDGE

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int n;

    cin>>n;

    string s;

    c=0;
    for(int i=0;i<n;i++)
    {
    	cin>>s;
    	str.push_back(s);
    	string a=s.substr(0,2);
    	string b=s.substr(1,2);
    	if(idx.count(a)==0)
    	    		idx[a]=c++;
    	if(idx.count(b)==0)
    	    		idx[b]=c++;

    	d[idx[a]]++;
    	d[idx[b]]--;
    }

    v.resize(c+2);
    for(int i=0;i<n;i++)
    {
    	string a=str[i].substr(0,2);
    	string b=str[i].substr(1,2);
    	//cout<<a<<" "<<b<<" "<<str[i]<<endl;
    	v[idx[a]].push_back(pr(idx[b],i));
    }
    int k=0;
    int st=0;

    for(int i=0;i<c;i++)
    {
    	int a=d[i];
    	if(a==1 || a==-1)
    	{
    		k++;
    		if(d[i]>0)
    			st=i;
    		else
    			en=i;
    	}
    	else if(a!=0)
    	{
    		k=4;
    	}
    }

    if(k==0 || k==2)
    {
    	ret="";

    	euler(st);
    	//reverse(q.begin(),q.end());
		ret+=str[q.top()];q.pop();
		//cout<<ret<<endl;
		while(q.size())
		{
			//cout<<str[q.top()]<<endl;
			ret+=str[q.top()].substr(2,1);
			q.pop();
		}
    	cout<<"YES\n"<<ret<<endl;
    }
    else
    	cout<<"NO\n";

    return 0;

}


#include<bits/stdtr1c++.h>
using namespace std;

vector<string> str;
map<string,int> idx;
typedef pair<int,int>pr;
vector<vector<pr > >v;
int d[70*70];
int c;
int vis[300009];
int en;
string ret;
stack<int> q;
void euler(int a)
{

	for(int i=0;i<v[a].size();i++)
	{
		if(vis[v[a][i].second])
			continue;
		vis[v[a][i].second]=1;
		euler(v[a][i].first);
		q.push(v[a][i].second);

	}

}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("2.in","r",stdin);

    #endif // ONLINE_JUDGE

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int n;

    cin>>n;

    string s;

    c=0;
    for(int i=0;i<n;i++)
    {
    	cin>>s;
    	str.push_back(s);
    	string a=s.substr(0,2);
    	string b=s.substr(1,2);
    	if(idx.count(a)==0)
    	    		idx[a]=c++;
    	if(idx.count(b)==0)
    	    		idx[b]=c++;

    	d[idx[a]]++;
    	d[idx[b]]--;
    }

    v.resize(c+2);
    for(int i=0;i<n;i++)
    {
    	string a=str[i].substr(0,2);
    	string b=str[i].substr(1,2);
    	//cout<<a<<" "<<b<<" "<<str[i]<<endl;
    	v[idx[a]].push_back(pr(idx[b],i));
    }
    int k=0;
    int st=0;

    for(int i=0;i<c;i++)
    {
    	int a=d[i];
    	//cout<<a<<" ";
    	if(a==1 || a==-1)
    	{
    		k++;
    		if(d[i]>0)
    			st=i;
    		else
    			en=i;
    	}
    	else if(a!=0)
    	{
    		k=4;
    	}
    }

    if(k==0 || k==2)
    {
    	ret="";

    	euler(st);
    	//reverse(q.begin(),q.end());
		ret+=str[q.top()];q.pop();
		//cout<<ret<<endl;
		while(q.size())
		{
			//cout<<str[q.top()]<<endl;
			ret+=str[q.top()].substr(2,1);
			q.pop();
		}
		if(ret.size()==n+2)
			cout<<"YES\n"<<ret<<endl;
		else
			cout<<"NO\n";//cout<<"NO\n";
    }
    else
    	cout<<"NO\n";

    return 0;

}


#include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
#define tpl(...) make_tuple(__VA_ARGS__)
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<int,int> pii;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
template<typename Ch,typename Tr,typename C,typename=decltype(begin(C()))>basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>&os,
const C& c){os<<'[';for(auto i=begin(c);i!=end(c);++i)os<<(i==begin(c)?"":" ")<<*i;return os<<']';}
template<class S,class T>ostream&operator<<(ostream &o,const pair<S,T>&t){return o<<'('<<t.first<<','<<t.second<<')';}
template<int N,class Tp>void output(ostream&,const Tp&){}
template<int N,class Tp,class,class ...Ts>void output(ostream &o,const Tp&t){if(N)o<<',';o<<get<N>(t);output<N+1,Tp,Ts...>(o,t);}
template<class ...Ts>ostream&operator<<(ostream&o,const tuple<Ts...>&t){o<<'(';output<0,tuple<Ts...>,Ts...>(o,t);return o<<')';}
template<class T>void output(T t,char z=10){if(t<0)t=-t,putchar(45);int c[20];
int k=0;while(t)c[k++]=t%10,t/=10;for(k||(c[k++]=0);k;)putchar(c[--k]^48);putchar(z);}
template<class T>void outputs(T t){output(t);}
template<class S,class ...T>void outputs(S a,T...t){output(a,32);outputs(t...);}
template<class T>void output(T *a,int n){REP(i,n)cout<<a[i]<<(i!=n-1?',':'\n');}
template<class T>void output(T *a,int n,int m){REP(i,n)output(a[i],m);}
template<class T>bool input(T &t){int n=1,c;for(t=0;!isdigit(c=getchar())&&~c&&c-45;);
if(!~c)return 0;for(c-45&&(n=0,t=c^48);isdigit(c=getchar());)t=10*t+c-48;t=n?-t:t;return 1;}
template<class S,class ...T>bool input(S&a,T&...t){input(a);return input(t...);}
template<class T>bool inputs(T *a, int n) { REP(i,n) if(!input(a[i])) return 0; return 1;}

int enc(char c) {
  if (isupper(c)) return 10+c-'A';
  else if (islower(c)) return 10+26+c-'a';
  return c-'0';
}
// 62*62=3844
int enc(const string &s) {
  return enc(s[0])*62+enc(s[1]);
}
char dec_char(int x){
  if (x<10) return '0'+x;
  if (x<36) return 'A'+x-10;
  return 'a'+x-10-26;
}
string dec(int x) {
  return string(1,dec_char(x/62))+string(1,dec_char(x%62));
}
template<int MAX_V, int MAX_E>
struct EulerPath {
  struct Edge {
    int s,t,next;
    Edge(){}
    Edge(int s, int t, int next) : s(s),t(t),next(next) {}
  };
  int n;
  Edge edge[MAX_E+10];
  int head[MAX_V+10];
  int cnt;
  void add_edge(int s, int t) {
    edge[cnt] = Edge(s,t,head[s]); head[s] = cnt++;
  }
  void init(int _n) {
    n = _n;
    cnt = 2;
  }
  int path[MAX_E+10];
  int pn;
  void visit(int a) {
    int k;
    while((k = head[a])) {
      int b = edge[k].t;
      head[a] = edge[k].next;
      visit(b);
    }
    path[pn++] = a;
  }
  bool run() {
    vector<int> deg(4000);
    int s = -1, m = 0;
    REP(v,n) {
      for (int k=head[v]; k; k=edge[k].next) {
        s = edge[k].t;
        deg[v]++;
        deg[edge[k].t]--;
        m++;
      }
    }
    int ct = 0;
    REP(i,4000) {
      if (deg[i]) {
        ct++;
        if (deg[i] > 0) s = i;
      }
    }
    if (ct > 2) return 0;
    pn = 0;
    visit(s);
    reverse(path, path+pn);
    return pn == m+1;
  }
};
int main() {
  int n;
  while(cin >> n) {
    static EulerPath<4000,200010> ep;
    ep.init(4000);
    REP(i,n) {
      string s;
      cin >> s;
      int a = enc(s.substr(0,2));
      int b = enc(s.substr(1,2));
      ep.add_edge(a,b);
    }
    if (ep.run()) {
      puts("YES");
      REP(i,ep.pn) {
        int x = ep.path[i];
        putchar(dec_char(x/62));
      }
      putchar(dec_char(ep.path[ep.pn-1]%62));
      puts("");
    } else {
      puts("NO");
    }
  }
}


#include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
#define tpl(...) make_tuple(__VA_ARGS__)
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<int,int> pii;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
template<typename Ch,typename Tr,typename C,typename=decltype(begin(C()))>basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>&os,
const C& c){os<<'[';for(auto i=begin(c);i!=end(c);++i)os<<(i==begin(c)?"":" ")<<*i;return os<<']';}
template<class S,class T>ostream&operator<<(ostream &o,const pair<S,T>&t){return o<<'('<<t.first<<','<<t.second<<')';}
template<int N,class Tp>void output(ostream&,const Tp&){}
template<int N,class Tp,class,class ...Ts>void output(ostream &o,const Tp&t){if(N)o<<',';o<<get<N>(t);output<N+1,Tp,Ts...>(o,t);}
template<class ...Ts>ostream&operator<<(ostream&o,const tuple<Ts...>&t){o<<'(';output<0,tuple<Ts...>,Ts...>(o,t);return o<<')';}
template<class T>void output(T t,char z=10){if(t<0)t=-t,putchar(45);int c[20];
int k=0;while(t)c[k++]=t%10,t/=10;for(k||(c[k++]=0);k;)putchar(c[--k]^48);putchar(z);}
template<class T>void outputs(T t){output(t);}
template<class S,class ...T>void outputs(S a,T...t){output(a,32);outputs(t...);}
template<class T>void output(T *a,int n){REP(i,n)cout<<a[i]<<(i!=n-1?',':'\n');}
template<class T>void output(T *a,int n,int m){REP(i,n)output(a[i],m);}
template<class T>bool input(T &t){int n=1,c;for(t=0;!isdigit(c=getchar())&&~c&&c-45;);
if(!~c)return 0;for(c-45&&(n=0,t=c^48);isdigit(c=getchar());)t=10*t+c-48;t=n?-t:t;return 1;}
template<class S,class ...T>bool input(S&a,T&...t){input(a);return input(t...);}
template<class T>bool inputs(T *a, int n) { REP(i,n) if(!input(a[i])) return 0; return 1;}

int enc(char c) {
  if (isupper(c)) return 10+c-'A';
  else if (islower(c)) return 10+26+c-'a';
  return c-'0';
}
// 62*62=3844
int enc(const string &s) {
  return enc(s[0])*62+enc(s[1]);
}
char dec_char(int x){
  if (x<10) return '0'+x;
  if (x<36) return 'A'+x-10;
  return 'a'+x-10-26;
}
string dec(int x) {
  return string(1,dec_char(x/62))+string(1,dec_char(x%62));
}
template<int MAX_V, int MAX_E>
struct EulerPath {
  struct Edge {
    int s,t,next;
    Edge(){}
    Edge(int s, int t, int next) : s(s),t(t),next(next) {}
  };
  int n;
  Edge edge[MAX_E+10];
  int head[MAX_V+10];
  int cnt;
  void add_edge(int s, int t) {
    edge[cnt] = Edge(s,t,head[s]); head[s] = cnt++;
  }
  void init(int _n) {
    n = _n;
    cnt = 2;
  }
  int path[MAX_E+10];
  int pn;
  void visit(int a) {
    int k;
    while((k = head[a])) {
      int b = edge[k].t;
      head[a] = edge[k].next;
      visit(b);
    }
    path[pn++] = a;
  }
  bool run() {
    vector<int> deg(4000);
    int s = -1, m = 0;
    REP(v,n) {
      for (int k=head[v]; k; k=edge[k].next) {
        s = edge[k].t;
        deg[v]++;
        deg[edge[k].t]--;
        m++;
      }
    }
    int ct = 0;
    REP(i,4000) {
      if (deg[i]) {
        ct++;
        if (deg[i] > 0) s = i;
      }
    }
    if (ct > 2) return 0;
    pn = 0;
    visit(s);
    reverse(path, path+pn);
    return pn == m+1;
  }
};
int main() {
  int n;
  while(cin >> n) {
    static EulerPath<4000,100010> ep;
    ep.init(4000);
    REP(i,n) {
      string s;
      cin >> s;
      int a = enc(s.substr(0,2));
      int b = enc(s.substr(1,2));
      ep.add_edge(a,b);
    }
    if (ep.run()) {
      puts("YES");
      REP(i,ep.pn) {
        int x = ep.path[i];
        putchar(dec_char(x/62));
      }
      putchar(dec_char(ep.path[ep.pn-1]%62));
      puts("");
    } else {
      puts("NO");
    }
  }
}


#include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
#define tpl(...) make_tuple(__VA_ARGS__)
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<int,int> pii;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
template<typename Ch,typename Tr,typename C,typename=decltype(begin(C()))>basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>&os,
const C& c){os<<'[';for(auto i=begin(c);i!=end(c);++i)os<<(i==begin(c)?"":" ")<<*i;return os<<']';}
template<class S,class T>ostream&operator<<(ostream &o,const pair<S,T>&t){return o<<'('<<t.first<<','<<t.second<<')';}
template<int N,class Tp>void output(ostream&,const Tp&){}
template<int N,class Tp,class,class ...Ts>void output(ostream &o,const Tp&t){if(N)o<<',';o<<get<N>(t);output<N+1,Tp,Ts...>(o,t);}
template<class ...Ts>ostream&operator<<(ostream&o,const tuple<Ts...>&t){o<<'(';output<0,tuple<Ts...>,Ts...>(o,t);return o<<')';}
template<class T>void output(T t,char z=10){if(t<0)t=-t,putchar(45);int c[20];
int k=0;while(t)c[k++]=t%10,t/=10;for(k||(c[k++]=0);k;)putchar(c[--k]^48);putchar(z);}
template<class T>void outputs(T t){output(t);}
template<class S,class ...T>void outputs(S a,T...t){output(a,32);outputs(t...);}
template<class T>void output(T *a,int n){REP(i,n)cout<<a[i]<<(i!=n-1?',':'\n');}
template<class T>void output(T *a,int n,int m){REP(i,n)output(a[i],m);}
template<class T>bool input(T &t){int n=1,c;for(t=0;!isdigit(c=getchar())&&~c&&c-45;);
if(!~c)return 0;for(c-45&&(n=0,t=c^48);isdigit(c=getchar());)t=10*t+c-48;t=n?-t:t;return 1;}
template<class S,class ...T>bool input(S&a,T&...t){input(a);return input(t...);}
template<class T>bool inputs(T *a, int n) { REP(i,n) if(!input(a[i])) return 0; return 1;}

int enc(char c) {
  if (isupper(c)) return 10+c-'A';
  else if (islower(c)) return 10+26+c-'a';
  return c-'0';
}
// 62*62=3844
int enc(const string &s) {
  return enc(s[0])*62+enc(s[1]);
}
char dec_char(int x){
  if (x<10) return '0'+x;
  if (x<36) return 'A'+x-10;
  return 'a'+x-10-26;
}
string dec(int x) {
  return string(1,dec_char(x/62))+string(1,dec_char(x%62));
}
vector<int> g[4000];
vector<int> path;
void visit(int a) {
  while(g[a].size()) {
    int b = g[a].back();
    g[a].pop_back();
    visit(b);
  }
  path.push_back(a);
}
int main() {
  int n;
  while(cin >> n) {
    REP(i,4000) g[i].clear();
    REP(i,n) {
      string s;
      cin >> s;
      int a = enc(s.substr(0,2));
      int b = enc(s.substr(1,2));
      g[a].push_back(b);
    }
    vector<int> deg(4000);
    int s = -1;
    REP(i,4000) {
      for (int j : g[i]) {
        s = j;
        deg[i]++;
        deg[j]--;
      }
    }
    vector<int> v;
    REP(i,4000) {
      if (deg[i]) v.push_back(i);
    }
    if (v.size() > 2) {
      cout << "NO" << endl;
      continue;
    }
    if (v.size() == 2) {
      if (deg[v[0]] > 0) s = v[0];
      else s = v[1];
    }
    path.clear();
    visit(s);
    reverse(ALL(path));
    puts("YES");
    for (int x : path) {
      putchar(dec_char(x/62));
    }
    putchar(dec_char(path.back()%62));
    puts("");
  }
}


#include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
#define tpl(...) make_tuple(__VA_ARGS__)
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<int,int> pii;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
template<typename Ch,typename Tr,typename C,typename=decltype(begin(C()))>basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>&os,
const C& c){os<<'[';for(auto i=begin(c);i!=end(c);++i)os<<(i==begin(c)?"":" ")<<*i;return os<<']';}
template<class S,class T>ostream&operator<<(ostream &o,const pair<S,T>&t){return o<<'('<<t.first<<','<<t.second<<')';}
template<int N,class Tp>void output(ostream&,const Tp&){}
template<int N,class Tp,class,class ...Ts>void output(ostream &o,const Tp&t){if(N)o<<',';o<<get<N>(t);output<N+1,Tp,Ts...>(o,t);}
template<class ...Ts>ostream&operator<<(ostream&o,const tuple<Ts...>&t){o<<'(';output<0,tuple<Ts...>,Ts...>(o,t);return o<<')';}
template<class T>void output(T t,char z=10){if(t<0)t=-t,putchar(45);int c[20];
int k=0;while(t)c[k++]=t%10,t/=10;for(k||(c[k++]=0);k;)putchar(c[--k]^48);putchar(z);}
template<class T>void outputs(T t){output(t);}
template<class S,class ...T>void outputs(S a,T...t){output(a,32);outputs(t...);}
template<class T>void output(T *a,int n){REP(i,n)cout<<a[i]<<(i!=n-1?',':'\n');}
template<class T>void output(T *a,int n,int m){REP(i,n)output(a[i],m);}
template<class T>bool input(T &t){int n=1,c;for(t=0;!isdigit(c=getchar())&&~c&&c-45;);
if(!~c)return 0;for(c-45&&(n=0,t=c^48);isdigit(c=getchar());)t=10*t+c-48;t=n?-t:t;return 1;}
template<class S,class ...T>bool input(S&a,T&...t){input(a);return input(t...);}
template<class T>bool inputs(T *a, int n) { REP(i,n) if(!input(a[i])) return 0; return 1;}

int enc(char c) {
  if (isupper(c)) return 10+c-'A';
  else if (islower(c)) return 10+26+c-'a';
  return c-'0';
}
// 62*62=3844
int enc(const string &s) {
  return enc(s[0])*62+enc(s[1]);
}
char dec_char(int x){
  if (x<10) return '0'+x;
  if (x<36) return 'A'+x-10;
  return 'a'+x-10-26;
}
string dec(int x) {
  return string(1,dec_char(x/62))+string(1,dec_char(x%62));
}
template<int MAX_V, int MAX_E>
struct EulerPath {
  struct Edge {
    int s,t,next;
    Edge(){}
    Edge(int s, int t, int next) : s(s),t(t),next(next) {}
  };
  int n;
  Edge edge[MAX_E+10];
  int head[MAX_V+10];
  int cnt;
  void add_edge(int s, int t) {
    edge[cnt] = Edge(s,t,head[s]); head[s] = cnt++;
  }
  void init(int _n) {
    n = _n;
    REP(i,n) head[i] = 0;
    cnt = 2;
  }
  int path[MAX_E+10];
  int pn;
  void visit(int a) {
    int k;
    while((k = head[a])) {
      int b = edge[k].t;
      head[a] = edge[k].next;
      visit(b);
    }
    path[pn++] = a;
  }
  bool run() {
    vector<int> deg(4000);
    int s = -1, m = 0;
    REP(v,n) {
      for (int k=head[v]; k; k=edge[k].next) {
        s = edge[k].t;
        deg[v]++;
        deg[edge[k].t]--;
        m++;
      }
    }
    int ct = 0;
    REP(i,4000) {
      if (deg[i]) {
        ct++;
        if (deg[i] > 0) s = i;
      }
    }
    if (ct > 2) return 0;
    if (ct == 2 && deg[s] != 1) return 0;
    pn = 0;
    visit(s);
    reverse(path, path+pn);
    return pn == m+1;
  }
};
int main() {
  int n;
  while(cin >> n) {
    static EulerPath<4000,200010> ep;
    ep.init(4000);
    REP(i,n) {
      string s;
      cin >> s;
      int a = enc(s.substr(0,2));
      int b = enc(s.substr(1,2));
      ep.add_edge(a,b);
    }
    if (ep.run()) {
      puts("YES");
      REP(i,ep.pn) {
        int x = ep.path[i];
        putchar(dec_char(x/62));
      }
      putchar(dec_char(ep.path[ep.pn-1]%62));
      puts("");
    } else {
      puts("NO");
    }
  }
}


#include <unordered_map>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
  int n;
void dfs2(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs2(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
void error()
{
	cout << "NO" << endl;
	exit(0);
}

const int MAX_BUF = 2e+7 + 10;
char bufRes[MAX_BUF];

struct Node;
struct Edge
{
	Node *node;
	bool go;
	Edge (Node *nd) :
		node(nd), go(false) {}
};

struct Node
{
	char val[3];
	vector<Edge*> vec;
	bool go;
	int index;
	inline Node (char a, char b)
	{
		val[0] = a;
		val[1] = b;
		val[2] = 0;
		go = false;
	}
};

Node **gr;
const int cntChar = 256;
Node *nodes[cntChar][cntChar] = {0};

int cntNodes = 0;
inline void addEdge(int a, int b, int c)
{
	if (nodes[a][b] == nullptr)
	{
		nodes[a][b] = new Node(a, b);
		++cntNodes;
	}
	if (nodes[b][c] == nullptr)
	{
		nodes[b][c] = new Node(b, c);
		++cntNodes;
	}

	nodes[a][b]->vec.push_back(new Edge(nodes[b][c]));
}

vector<int> res;

void dfs1(int index)
{
	stack<int> st;
	st.push(index);
	int *lastNode = new int[cntNodes]();

	while (!st.empty())
	{
		int cur = st.top();
		bool found = false;
		for (int q = lastNode[cur]; !found && q < (int)gr[cur]->vec.size(); ++q)
		{
			Edge *next = gr[cur]->vec[q];
			if (next->go)
				continue;
			lastNode[cur] = q + 1;
			next->go = true;
			st.push(next->node->index);
			found = true;
		}
		if (!found)
		{
			st.pop();
			res.push_back(cur);
		}
	}
}

void dfs(int index)
{
	for (int q = 0; q < (int)gr[index]->vec.size(); ++q)
	{
		Edge *next = gr[index]->vec[q];
		if (next->go)
			continue;
		next->go = true;
		dfs(next->node->index);
	}
	res.push_back(index);
}

int main1()
{
	/*
	#pragma message "FREOPEN"
	freopen("tmp", "r", stdin);
//	*/

	char buf[10];
	fgets(buf, 10, stdin);
	for (int q = 0; q < n; ++q)
	{
		fgets(buf, 10, stdin);
		addEdge(buf[0], buf[1], buf[2]);
	}

	gr = new Node*[cntNodes];
	int cnt = 0;
	for (int q = 0; q < cntChar; ++q)
		for (int i = 0; i < cntChar; ++i)
			if (nodes[q][i] != nullptr)
			{
				nodes[q][i]->index = cnt;
				gr[cnt++] = nodes[q][i];
			}

	int *cntFrom = new int[cntNodes](),
		*cntTo = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
	{
		cntFrom[q] = gr[q]->vec.size();
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			++cntTo[gr[q]->vec[i]->node->index];
	}

	int *bal = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
		bal[q] = cntFrom[q] - cntTo[q];

	int indexFrom = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] < 0)
		{
			if (-bal[q] % 2 != 1)
				error();
			if (indexFrom == -1)
				indexFrom = q;
			else
				error();
		}

	int indexTo = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] > 0 && bal[q] % 2 == 1)
		{
			if (bal[q] % 2 != 1)
				error();
			if (indexTo == -1)
				indexTo = q;
			else
				error();
		}

	if ((indexFrom == -1) ^ (indexTo == -1))
		error();

	int startIndex = indexTo == -1 ? 0 : indexTo;
//	gr[indexFrom]->vec.push_back(new Edge(gr[indexTo]));

	// DEBUG
	/*
	for (int q = 0; q < cntNodes; ++q)
	{
		cout << gr[q]->val << " : ";
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			cout << gr[q]->vec[i]->node->val << ' ';
		cout << endl;
	} // */

	dfs1(startIndex);

	// Debug
	/*
	for (auto x : res)
		cout << x << ' ';
	cout << endl; // */

	cnt = 0;
	reverse(res.begin(), res.end());
	bufRes[cnt++] = gr[res[0]]->val[0];

	for (int q = 0; q < (int)res.size(); ++q)
		bufRes[cnt++] = gr[res[q]]->val[1];
	bufRes[cnt] = 0;

	if (cnt != n + 2)
		error();

	cout << "YES" << endl;
	cout << bufRes << endl;

	return 0;
}

int main(){
  cin>>n;
  if(n>200){
    main1();
    return 0;
  }
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs2(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}


#include <unordered_map>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
  int n;
void dfs2(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs2(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
void error()
{
	cout << "NO" << endl;
	exit(0);
}

const int MAX_BUF = 2e+7 + 10;
char bufRes[MAX_BUF];

struct Node;
struct Edge
{
	Node *node;
	bool go;
	Edge (Node *nd) :
		node(nd), go(false) {}
};

struct Node
{
	char val[3];
	vector<Edge*> vec;
	bool go;
	int index;
	inline Node (char a, char b)
	{
		val[0] = a;
		val[1] = b;
		val[2] = 0;
		go = false;
	}
};

Node **gr;
const int cntChar = 256;
Node *nodes[cntChar][cntChar] = {0};

int cntNodes = 0;
inline void addEdge(int a, int b, int c)
{
	if (nodes[a][b] == nullptr)
	{
		nodes[a][b] = new Node(a, b);
		++cntNodes;
	}
	if (nodes[b][c] == nullptr)
	{
		nodes[b][c] = new Node(b, c);
		++cntNodes;
	}

	nodes[a][b]->vec.push_back(new Edge(nodes[b][c]));
}

vector<int> res;

void dfs1(int index)
{
	stack<int> st;
	st.push(index);
	int *lastNode = new int[cntNodes]();

	while (!st.empty())
	{
		int cur = st.top();
		bool found = false;
		for (int q = lastNode[cur]; !found && q < (int)gr[cur]->vec.size(); ++q)
		{
			Edge *next = gr[cur]->vec[q];
			if (next->go)
				continue;
			lastNode[cur] = q + 1;
			next->go = true;
			st.push(next->node->index);
			found = true;
		}
		if (!found)
		{
			st.pop();
			res.push_back(cur);
		}
	}
}

void dfs(int index)
{
	for (int q = 0; q < (int)gr[index]->vec.size(); ++q)
	{
		Edge *next = gr[index]->vec[q];
		if (next->go)
			continue;
		next->go = true;
		dfs(next->node->index);
	}
	res.push_back(index);
}

int main1()
{
	/*
	#pragma message "FREOPEN"
	freopen("tmp", "r", stdin);
//	*/

	char buf[10];
	fgets(buf, 10, stdin);
	for (int q = 0; q < n; ++q)
	{
		fgets(buf, 10, stdin);
		addEdge(buf[0], buf[1], buf[2]);
	}

	gr = new Node*[cntNodes];
	int cnt = 0;
	for (int q = 0; q < cntChar; ++q)
		for (int i = 0; i < cntChar; ++i)
			if (nodes[q][i] != nullptr)
			{
				nodes[q][i]->index = cnt;
				gr[cnt++] = nodes[q][i];
			}

	int *cntFrom = new int[cntNodes](),
		*cntTo = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
	{
		cntFrom[q] = gr[q]->vec.size();
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			++cntTo[gr[q]->vec[i]->node->index];
	}

	int *bal = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
		bal[q] = cntFrom[q] - cntTo[q];

	int indexFrom = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] < 0)
		{
			if (-bal[q] % 2 != 1)
				error();
			if (indexFrom == -1)
				indexFrom = q;
			else
				error();
		}

	int indexTo = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] > 0 && bal[q] % 2 == 1)
		{
			if (bal[q] % 2 != 1)
				error();
			if (indexTo == -1)
				indexTo = q;
			else
				error();
		}

	if ((indexFrom == -1) ^ (indexTo == -1))
		error();

	int startIndex = indexTo == -1 ? 0 : indexTo;
//	gr[indexFrom]->vec.push_back(new Edge(gr[indexTo]));

	// DEBUG
	/*
	for (int q = 0; q < cntNodes; ++q)
	{
		cout << gr[q]->val << " : ";
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			cout << gr[q]->vec[i]->node->val << ' ';
		cout << endl;
	} // */

	dfs1(startIndex);

	// Debug
	/*
	for (auto x : res)
		cout << x << ' ';
	cout << endl; // */

	cnt = 0;
	reverse(res.begin(), res.end());
	bufRes[cnt++] = gr[res[0]]->val[0];

	for (int q = 0; q < (int)res.size(); ++q)
		bufRes[cnt++] = gr[res[q]]->val[1];
	bufRes[cnt] = 0;

	if (cnt != n + 2)
		error();

	cout << "YES" << endl;
	cout << bufRes << endl;

	return 0;
}

int main(){
  cin>>n;
  if(n>100){
    main1();
    return 0;
  }
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs2(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}


#include <unordered_map>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
  int n;
void dfs2(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
void error()
{
	cout << "NO" << endl;
	exit(0);
}

const int MAX_BUF = 2e+7 + 10;
char bufRes[MAX_BUF];

struct Node;
struct Edge
{
	Node *node;
	bool go;
	Edge (Node *nd) :
		node(nd), go(false) {}
};

struct Node
{
	char val[3];
	vector<Edge*> vec;
	bool go;
	int index;
	inline Node (char a, char b)
	{
		val[0] = a;
		val[1] = b;
		val[2] = 0;
		go = false;
	}
};

Node **gr;
const int cntChar = 256;
Node *nodes[cntChar][cntChar] = {0};

int cntNodes = 0;
inline void addEdge(int a, int b, int c)
{
	if (nodes[a][b] == nullptr)
	{
		nodes[a][b] = new Node(a, b);
		++cntNodes;
	}
	if (nodes[b][c] == nullptr)
	{
		nodes[b][c] = new Node(b, c);
		++cntNodes;
	}

	nodes[a][b]->vec.push_back(new Edge(nodes[b][c]));
}

vector<int> res;

void dfs1(int index)
{
	stack<int> st;
	st.push(index);
	int *lastNode = new int[cntNodes]();

	while (!st.empty())
	{
		int cur = st.top();
		bool found = false;
		for (int q = lastNode[cur]; !found && q < (int)gr[cur]->vec.size(); ++q)
		{
			Edge *next = gr[cur]->vec[q];
			if (next->go)
				continue;
			lastNode[cur] = q + 1;
			next->go = true;
			st.push(next->node->index);
			found = true;
		}
		if (!found)
		{
			st.pop();
			res.push_back(cur);
		}
	}
}

void dfs(int index)
{
	for (int q = 0; q < (int)gr[index]->vec.size(); ++q)
	{
		Edge *next = gr[index]->vec[q];
		if (next->go)
			continue;
		next->go = true;
		dfs(next->node->index);
	}
	res.push_back(index);
}

int main1()
{
	/*
	#pragma message "FREOPEN"
	freopen("tmp", "r", stdin);
//	*/

	char buf[10];
	fgets(buf, 10, stdin);
	for (int q = 0; q < n; ++q)
	{
		fgets(buf, 10, stdin);
		addEdge(buf[0], buf[1], buf[2]);
	}

	gr = new Node*[cntNodes];
	int cnt = 0;
	for (int q = 0; q < cntChar; ++q)
		for (int i = 0; i < cntChar; ++i)
			if (nodes[q][i] != nullptr)
			{
				nodes[q][i]->index = cnt;
				gr[cnt++] = nodes[q][i];
			}

	int *cntFrom = new int[cntNodes](),
		*cntTo = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
	{
		cntFrom[q] = gr[q]->vec.size();
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			++cntTo[gr[q]->vec[i]->node->index];
	}

	int *bal = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
		bal[q] = cntFrom[q] - cntTo[q];

	int indexFrom = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] < 0)
		{
			if (-bal[q] % 2 != 1)
				error();
			if (indexFrom == -1)
				indexFrom = q;
			else
				error();
		}

	int indexTo = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] > 0 && bal[q] % 2 == 1)
		{
			if (bal[q] % 2 != 1)
				error();
			if (indexTo == -1)
				indexTo = q;
			else
				error();
		}

	if ((indexFrom == -1) ^ (indexTo == -1))
		error();

	int startIndex = indexTo == -1 ? 0 : indexTo;
//	gr[indexFrom]->vec.push_back(new Edge(gr[indexTo]));

	// DEBUG
	/*
	for (int q = 0; q < cntNodes; ++q)
	{
		cout << gr[q]->val << " : ";
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			cout << gr[q]->vec[i]->node->val << ' ';
		cout << endl;
	} // */

	dfs1(startIndex);

	// Debug
	/*
	for (auto x : res)
		cout << x << ' ';
	cout << endl; // */

	cnt = 0;
	reverse(res.begin(), res.end());
	bufRes[cnt++] = gr[res[0]]->val[0];

	for (int q = 0; q < (int)res.size(); ++q)
		bufRes[cnt++] = gr[res[q]]->val[1];
	bufRes[cnt] = 0;

	if (cnt != n + 2)
		error();

	cout << "YES" << endl;
	cout << bufRes << endl;

	return 0;
}

int main(){
  cin>>n;
  if(n>10000){
    main1();
    return 0;
  }
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs2(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}


#include <unordered_map>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
  int n;
void dfs2(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs2(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
void error()
{
	cout << "NO" << endl;
	exit(0);
}

const int MAX_BUF = 2e+7 + 10;
char bufRes[MAX_BUF];

struct Node;
struct Edge
{
	Node *node;
	bool go;
	Edge (Node *nd) :
		node(nd), go(false) {}
};

struct Node
{
	char val[3];
	vector<Edge*> vec;
	bool go;
	int index;
	inline Node (char a, char b)
	{
		val[0] = a;
		val[1] = b;
		val[2] = 0;
		go = false;
	}
};

Node **gr;
const int cntChar = 256;
Node *nodes[cntChar][cntChar] = {0};

int cntNodes = 0;
inline void addEdge(int a, int b, int c)
{
	if (nodes[a][b] == nullptr)
	{
		nodes[a][b] = new Node(a, b);
		++cntNodes;
	}
	if (nodes[b][c] == nullptr)
	{
		nodes[b][c] = new Node(b, c);
		++cntNodes;
	}

	nodes[a][b]->vec.push_back(new Edge(nodes[b][c]));
}

vector<int> res;

void dfs1(int index)
{
	stack<int> st;
	st.push(index);
	int *lastNode = new int[cntNodes]();

	while (!st.empty())
	{
		int cur = st.top();
		bool found = false;
		for (int q = lastNode[cur]; !found && q < (int)gr[cur]->vec.size(); ++q)
		{
			Edge *next = gr[cur]->vec[q];
			if (next->go)
				continue;
			lastNode[cur] = q + 1;
			next->go = true;
			st.push(next->node->index);
			found = true;
		}
		if (!found)
		{
			st.pop();
			res.push_back(cur);
		}
	}
}

void dfs(int index)
{
	for (int q = 0; q < (int)gr[index]->vec.size(); ++q)
	{
		Edge *next = gr[index]->vec[q];
		if (next->go)
			continue;
		next->go = true;
		dfs(next->node->index);
	}
	res.push_back(index);
}

int main1()
{
	/*
	#pragma message "FREOPEN"
	freopen("tmp", "r", stdin);
//	*/

	char buf[10];
	fgets(buf, 10, stdin);
	for (int q = 0; q < n; ++q)
	{
		fgets(buf, 10, stdin);
		addEdge(buf[0], buf[1], buf[2]);
	}

	gr = new Node*[cntNodes];
	int cnt = 0;
	for (int q = 0; q < cntChar; ++q)
		for (int i = 0; i < cntChar; ++i)
			if (nodes[q][i] != nullptr)
			{
				nodes[q][i]->index = cnt;
				gr[cnt++] = nodes[q][i];
			}

	int *cntFrom = new int[cntNodes](),
		*cntTo = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
	{
		cntFrom[q] = gr[q]->vec.size();
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			++cntTo[gr[q]->vec[i]->node->index];
	}

	int *bal = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
		bal[q] = cntFrom[q] - cntTo[q];

	int indexFrom = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] < 0)
		{
			if (-bal[q] % 2 != 1)
				error();
			if (indexFrom == -1)
				indexFrom = q;
			else
				error();
		}

	int indexTo = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] > 0 && bal[q] % 2 == 1)
		{
			if (bal[q] % 2 != 1)
				error();
			if (indexTo == -1)
				indexTo = q;
			else
				error();
		}

	if ((indexFrom == -1) ^ (indexTo == -1))
		error();

	int startIndex = indexTo == -1 ? 0 : indexTo;
//	gr[indexFrom]->vec.push_back(new Edge(gr[indexTo]));

	// DEBUG
	/*
	for (int q = 0; q < cntNodes; ++q)
	{
		cout << gr[q]->val << " : ";
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			cout << gr[q]->vec[i]->node->val << ' ';
		cout << endl;
	} // */

	dfs1(startIndex);

	// Debug
	/*
	for (auto x : res)
		cout << x << ' ';
	cout << endl; // */

	cnt = 0;
	reverse(res.begin(), res.end());
	bufRes[cnt++] = gr[res[0]]->val[0];

	for (int q = 0; q < (int)res.size(); ++q)
		bufRes[cnt++] = gr[res[q]]->val[1];
	bufRes[cnt] = 0;

	if (cnt != n + 2)
		error();

	cout << "YES" << endl;
	cout << bufRes << endl;

	return 0;
}

int main(){
  cin>>n;
  if(n>250){
    main1();
    return 0;
  }
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs2(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}


#include <unordered_map>
#include <iostream>
#include <vector>
using namespace std;
  int n;
void dfs2(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
void error()
{
	cout << "NO" << endl;
	exit(0);
}

const int MAX_BUF = 2e+7 + 10;
char bufRes[MAX_BUF];

struct Node;
struct Edge
{
	Node *node;
	bool go;
	Edge (Node *nd) :
		node(nd), go(false) {}
};

struct Node
{
	char val[3];
	vector<Edge*> vec;
	bool go;
	int index;
	inline Node (char a, char b)
	{
		val[0] = a;
		val[1] = b;
		val[2] = 0;
		go = false;
	}
};

Node **gr;
const int cntChar = 256;
Node *nodes[cntChar][cntChar] = {0};

int cntNodes = 0;
inline void addEdge(int a, int b, int c)
{
	if (nodes[a][b] == nullptr)
	{
		nodes[a][b] = new Node(a, b);
		++cntNodes;
	}
	if (nodes[b][c] == nullptr)
	{
		nodes[b][c] = new Node(b, c);
		++cntNodes;
	}

	nodes[a][b]->vec.push_back(new Edge(nodes[b][c]));
}

vector<int> res;

void dfs1(int index)
{
	stack<int> st;
	st.push(index);
	int *lastNode = new int[cntNodes]();

	while (!st.empty())
	{
		int cur = st.top();
		bool found = false;
		for (int q = lastNode[cur]; !found && q < (int)gr[cur]->vec.size(); ++q)
		{
			Edge *next = gr[cur]->vec[q];
			if (next->go)
				continue;
			lastNode[cur] = q + 1;
			next->go = true;
			st.push(next->node->index);
			found = true;
		}
		if (!found)
		{
			st.pop();
			res.push_back(cur);
		}
	}
}

void dfs(int index)
{
	for (int q = 0; q < (int)gr[index]->vec.size(); ++q)
	{
		Edge *next = gr[index]->vec[q];
		if (next->go)
			continue;
		next->go = true;
		dfs(next->node->index);
	}
	res.push_back(index);
}

int main1()
{
	/*
	#pragma message "FREOPEN"
	freopen("tmp", "r", stdin);
//	*/

	char buf[10];
	fgets(buf, 10, stdin);
	for (int q = 0; q < n; ++q)
	{
		fgets(buf, 10, stdin);
		addEdge(buf[0], buf[1], buf[2]);
	}

	gr = new Node*[cntNodes];
	int cnt = 0;
	for (int q = 0; q < cntChar; ++q)
		for (int i = 0; i < cntChar; ++i)
			if (nodes[q][i] != nullptr)
			{
				nodes[q][i]->index = cnt;
				gr[cnt++] = nodes[q][i];
			}

	int *cntFrom = new int[cntNodes](),
		*cntTo = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
	{
		cntFrom[q] = gr[q]->vec.size();
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			++cntTo[gr[q]->vec[i]->node->index];
	}

	int *bal = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
		bal[q] = cntFrom[q] - cntTo[q];

	int indexFrom = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] < 0)
		{
			if (-bal[q] % 2 != 1)
				error();
			if (indexFrom == -1)
				indexFrom = q;
			else
				error();
		}

	int indexTo = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] > 0 && bal[q] % 2 == 1)
		{
			if (bal[q] % 2 != 1)
				error();
			if (indexTo == -1)
				indexTo = q;
			else
				error();
		}

	if ((indexFrom == -1) ^ (indexTo == -1))
		error();

	int startIndex = indexTo == -1 ? 0 : indexTo;
//	gr[indexFrom]->vec.push_back(new Edge(gr[indexTo]));

	// DEBUG
	/*
	for (int q = 0; q < cntNodes; ++q)
	{
		cout << gr[q]->val << " : ";
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			cout << gr[q]->vec[i]->node->val << ' ';
		cout << endl;
	} // */

	dfs1(startIndex);

	// Debug
	/*
	for (auto x : res)
		cout << x << ' ';
	cout << endl; // */

	cnt = 0;
	reverse(res.begin(), res.end());
	bufRes[cnt++] = gr[res[0]]->val[0];

	for (int q = 0; q < (int)res.size(); ++q)
		bufRes[cnt++] = gr[res[q]]->val[1];
	bufRes[cnt] = 0;

	if (cnt != n + 2)
		error();

	cout << "YES" << endl;
	cout << bufRes << endl;

	return 0;
}

int main(){
  cin>>n;
  if(n>10000){
    main1();
    return 0;
  }
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs2(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}


#include <unordered_map>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
  int n;
void dfs2(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs2(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
void error()
{
	cout << "NO" << endl;
	exit(0);
}

const int MAX_BUF = 2e+7 + 10;
char bufRes[MAX_BUF];

struct Node;
struct Edge
{
	Node *node;
	bool go;
	Edge (Node *nd) :
		node(nd), go(false) {}
};

struct Node
{
	char val[3];
	vector<Edge*> vec;
	bool go;
	int index;
	inline Node (char a, char b)
	{
		val[0] = a;
		val[1] = b;
		val[2] = 0;
		go = false;
	}
};

Node **gr;
const int cntChar = 256;
Node *nodes[cntChar][cntChar] = {0};

int cntNodes = 0;
inline void addEdge(int a, int b, int c)
{
	if (nodes[a][b] == nullptr)
	{
		nodes[a][b] = new Node(a, b);
		++cntNodes;
	}
	if (nodes[b][c] == nullptr)
	{
		nodes[b][c] = new Node(b, c);
		++cntNodes;
	}

	nodes[a][b]->vec.push_back(new Edge(nodes[b][c]));
}

vector<int> res;

void dfs1(int index)
{
	stack<int> st;
	st.push(index);
	int *lastNode = new int[cntNodes]();

	while (!st.empty())
	{
		int cur = st.top();
		bool found = false;
		for (int q = lastNode[cur]; !found && q < (int)gr[cur]->vec.size(); ++q)
		{
			Edge *next = gr[cur]->vec[q];
			if (next->go)
				continue;
			lastNode[cur] = q + 1;
			next->go = true;
			st.push(next->node->index);
			found = true;
		}
		if (!found)
		{
			st.pop();
			res.push_back(cur);
		}
	}
}

void dfs(int index)
{
	for (int q = 0; q < (int)gr[index]->vec.size(); ++q)
	{
		Edge *next = gr[index]->vec[q];
		if (next->go)
			continue;
		next->go = true;
		dfs(next->node->index);
	}
	res.push_back(index);
}

int main1()
{
	/*
	#pragma message "FREOPEN"
	freopen("tmp", "r", stdin);
//	*/

	char buf[10];
	fgets(buf, 10, stdin);
	for (int q = 0; q < n; ++q)
	{
		fgets(buf, 10, stdin);
		addEdge(buf[0], buf[1], buf[2]);
	}

	gr = new Node*[cntNodes];
	int cnt = 0;
	for (int q = 0; q < cntChar; ++q)
		for (int i = 0; i < cntChar; ++i)
			if (nodes[q][i] != nullptr)
			{
				nodes[q][i]->index = cnt;
				gr[cnt++] = nodes[q][i];
			}

	int *cntFrom = new int[cntNodes](),
		*cntTo = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
	{
		cntFrom[q] = gr[q]->vec.size();
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			++cntTo[gr[q]->vec[i]->node->index];
	}

	int *bal = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
		bal[q] = cntFrom[q] - cntTo[q];

	int indexFrom = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] < 0)
		{
			if (-bal[q] % 2 != 1)
				error();
			if (indexFrom == -1)
				indexFrom = q;
			else
				error();
		}

	int indexTo = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] > 0 && bal[q] % 2 == 1)
		{
			if (bal[q] % 2 != 1)
				error();
			if (indexTo == -1)
				indexTo = q;
			else
				error();
		}

	if ((indexFrom == -1) ^ (indexTo == -1))
		error();

	int startIndex = indexTo == -1 ? 0 : indexTo;
//	gr[indexFrom]->vec.push_back(new Edge(gr[indexTo]));

	// DEBUG
	/*
	for (int q = 0; q < cntNodes; ++q)
	{
		cout << gr[q]->val << " : ";
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			cout << gr[q]->vec[i]->node->val << ' ';
		cout << endl;
	} // */

	dfs1(startIndex);

	// Debug
	/*
	for (auto x : res)
		cout << x << ' ';
	cout << endl; // */

	cnt = 0;
	reverse(res.begin(), res.end());
	bufRes[cnt++] = gr[res[0]]->val[0];

	for (int q = 0; q < (int)res.size(); ++q)
		bufRes[cnt++] = gr[res[q]]->val[1];
	bufRes[cnt] = 0;

	if (cnt != n + 2)
		error();

	cout << "YES" << endl;
	cout << bufRes << endl;

	return 0;
}

int main(){
  cin>>n;
  if(n>90){
    main1();
    return 0;
  }
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs2(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}


#include <unordered_map>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
  int n;
void dfs2(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs2(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
void error()
{
	cout << "NO" << endl;
	exit(0);
}

const int MAX_BUF = 2e+7 + 10;
char bufRes[MAX_BUF];

struct Node;
struct Edge
{
	Node *node;
	bool go;
	Edge (Node *nd) :
		node(nd), go(false) {}
};

struct Node
{
	char val[3];
	vector<Edge*> vec;
	bool go;
	int index;
	inline Node (char a, char b)
	{
		val[0] = a;
		val[1] = b;
		val[2] = 0;
		go = false;
	}
};

Node **gr;
const int cntChar = 256;
Node *nodes[cntChar][cntChar] = {0};

int cntNodes = 0;
inline void addEdge(int a, int b, int c)
{
	if (nodes[a][b] == nullptr)
	{
		nodes[a][b] = new Node(a, b);
		++cntNodes;
	}
	if (nodes[b][c] == nullptr)
	{
		nodes[b][c] = new Node(b, c);
		++cntNodes;
	}

	nodes[a][b]->vec.push_back(new Edge(nodes[b][c]));
}

vector<int> res;

void dfs1(int index)
{
	stack<int> st;
	st.push(index);
	int *lastNode = new int[cntNodes]();

	while (!st.empty())
	{
		int cur = st.top();
		bool found = false;
		for (int q = lastNode[cur]; !found && q < (int)gr[cur]->vec.size(); ++q)
		{
			Edge *next = gr[cur]->vec[q];
			if (next->go)
				continue;
			lastNode[cur] = q + 1;
			next->go = true;
			st.push(next->node->index);
			found = true;
		}
		if (!found)
		{
			st.pop();
			res.push_back(cur);
		}
	}
}

void dfs(int index)
{
	for (int q = 0; q < (int)gr[index]->vec.size(); ++q)
	{
		Edge *next = gr[index]->vec[q];
		if (next->go)
			continue;
		next->go = true;
		dfs(next->node->index);
	}
	res.push_back(index);
}

int main1()
{
	/*
	#pragma message "FREOPEN"
	freopen("tmp", "r", stdin);
//	*/

	char buf[10];
	fgets(buf, 10, stdin);
	for (int q = 0; q < n; ++q)
	{
		fgets(buf, 10, stdin);
		addEdge(buf[0], buf[1], buf[2]);
	}

	gr = new Node*[cntNodes];
	int cnt = 0;
	for (int q = 0; q < cntChar; ++q)
		for (int i = 0; i < cntChar; ++i)
			if (nodes[q][i] != nullptr)
			{
				nodes[q][i]->index = cnt;
				gr[cnt++] = nodes[q][i];
			}

	int *cntFrom = new int[cntNodes](),
		*cntTo = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
	{
		cntFrom[q] = gr[q]->vec.size();
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			++cntTo[gr[q]->vec[i]->node->index];
	}

	int *bal = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
		bal[q] = cntFrom[q] - cntTo[q];

	int indexFrom = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] < 0)
		{
			if (-bal[q] % 2 != 1)
				error();
			if (indexFrom == -1)
				indexFrom = q;
			else
				error();
		}

	int indexTo = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] > 0 && bal[q] % 2 == 1)
		{
			if (bal[q] % 2 != 1)
				error();
			if (indexTo == -1)
				indexTo = q;
			else
				error();
		}

	if ((indexFrom == -1) ^ (indexTo == -1))
		error();

	int startIndex = indexTo == -1 ? 0 : indexTo;
//	gr[indexFrom]->vec.push_back(new Edge(gr[indexTo]));

	// DEBUG
	/*
	for (int q = 0; q < cntNodes; ++q)
	{
		cout << gr[q]->val << " : ";
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			cout << gr[q]->vec[i]->node->val << ' ';
		cout << endl;
	} // */

	dfs1(startIndex);

	// Debug
	/*
	for (auto x : res)
		cout << x << ' ';
	cout << endl; // */

	cnt = 0;
	reverse(res.begin(), res.end());
	bufRes[cnt++] = gr[res[0]]->val[0];

	for (int q = 0; q < (int)res.size(); ++q)
		bufRes[cnt++] = gr[res[q]]->val[1];
	bufRes[cnt] = 0;

	if (cnt != n + 2)
		error();

	cout << "YES" << endl;
	cout << bufRes << endl;

	return 0;
}

int main(){
  cin>>n;
  if(n>93){
    main1();
    return 0;
  }
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs2(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}


#include <unordered_map>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
  int n;
void dfs2(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs2(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
void error()
{
	cout << "NO" << endl;
	exit(0);
}

const int MAX_BUF = 2e+7 + 10;
char bufRes[MAX_BUF];

struct Node;
struct Edge
{
	Node *node;
	bool go;
	Edge (Node *nd) :
		node(nd), go(false) {}
};

struct Node
{
	char val[3];
	vector<Edge*> vec;
	bool go;
	int index;
	inline Node (char a, char b)
	{
		val[0] = a;
		val[1] = b;
		val[2] = 0;
		go = false;
	}
};

Node **gr;
const int cntChar = 256;
Node *nodes[cntChar][cntChar] = {0};

int cntNodes = 0;
inline void addEdge(int a, int b, int c)
{
	if (nodes[a][b] == nullptr)
	{
		nodes[a][b] = new Node(a, b);
		++cntNodes;
	}
	if (nodes[b][c] == nullptr)
	{
		nodes[b][c] = new Node(b, c);
		++cntNodes;
	}

	nodes[a][b]->vec.push_back(new Edge(nodes[b][c]));
}

vector<int> res;

void dfs1(int index)
{
	stack<int> st;
	st.push(index);
	int *lastNode = new int[cntNodes]();

	while (!st.empty())
	{
		int cur = st.top();
		bool found = false;
		for (int q = lastNode[cur]; !found && q < (int)gr[cur]->vec.size(); ++q)
		{
			Edge *next = gr[cur]->vec[q];
			if (next->go)
				continue;
			lastNode[cur] = q + 1;
			next->go = true;
			st.push(next->node->index);
			found = true;
		}
		if (!found)
		{
			st.pop();
			res.push_back(cur);
		}
	}
}

void dfs(int index)
{
	for (int q = 0; q < (int)gr[index]->vec.size(); ++q)
	{
		Edge *next = gr[index]->vec[q];
		if (next->go)
			continue;
		next->go = true;
		dfs(next->node->index);
	}
	res.push_back(index);
}

int main1()
{
	/*
	#pragma message "FREOPEN"
	freopen("tmp", "r", stdin);
//	*/

	char buf[10];
	fgets(buf, 10, stdin);
	for (int q = 0; q < n; ++q)
	{
		fgets(buf, 10, stdin);
		addEdge(buf[0], buf[1], buf[2]);
	}

	gr = new Node*[cntNodes];
	int cnt = 0;
	for (int q = 0; q < cntChar; ++q)
		for (int i = 0; i < cntChar; ++i)
			if (nodes[q][i] != nullptr)
			{
				nodes[q][i]->index = cnt;
				gr[cnt++] = nodes[q][i];
			}

	int *cntFrom = new int[cntNodes](),
		*cntTo = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
	{
		cntFrom[q] = gr[q]->vec.size();
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			++cntTo[gr[q]->vec[i]->node->index];
	}

	int *bal = new int[cntNodes]();
	for (int q = 0; q < cntNodes; ++q)
		bal[q] = cntFrom[q] - cntTo[q];

	int indexFrom = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] < 0)
		{
			if (-bal[q] % 2 != 1)
				error();
			if (indexFrom == -1)
				indexFrom = q;
			else
				error();
		}

	int indexTo = -1;
	for (int q = 0; q < cntNodes; ++q)
		if (bal[q] > 0 && bal[q] % 2 == 1)
		{
			if (bal[q] % 2 != 1)
				error();
			if (indexTo == -1)
				indexTo = q;
			else
				error();
		}

	if ((indexFrom == -1) ^ (indexTo == -1))
		error();

	int startIndex = indexTo == -1 ? 0 : indexTo;
//	gr[indexFrom]->vec.push_back(new Edge(gr[indexTo]));

	// DEBUG
	/*
	for (int q = 0; q < cntNodes; ++q)
	{
		cout << gr[q]->val << " : ";
		for (int i = 0; i < (int)gr[q]->vec.size(); ++i)
			cout << gr[q]->vec[i]->node->val << ' ';
		cout << endl;
	} // */

	dfs1(startIndex);

	// Debug
	/*
	for (auto x : res)
		cout << x << ' ';
	cout << endl; // */

	cnt = 0;
	reverse(res.begin(), res.end());
	bufRes[cnt++] = gr[res[0]]->val[0];

	for (int q = 0; q < (int)res.size(); ++q)
		bufRes[cnt++] = gr[res[q]]->val[1];
	bufRes[cnt] = 0;

	if (cnt != n + 2)
		error();

	cout << "YES" << endl;
	cout << bufRes << endl;

	return 0;
}

int main(){
  cin>>n;
  if(n>10000){
    main1();
    return 0;
  }
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs2(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}


#include <unordered_map>
#include <iostream>
#include <vector>
using namespace std;
  int n;
void dfs(int i, vector<int> &path, int idx, vector<bool> &visited, vector<int> &ans, vector<string> &a, unordered_map< string, vector<int> > &begs){
  //cout<<"dfs"<<i<<endl;
  if(ans[n-1]!=-1)
    return;
  //cout<<"dfs here"<<i<<" "<<idx<<endl;
  if(n==idx){
    for(int k=0;k<n;++k)
      ans[k]=path[k];
    //cout<<"here ends"<<endl;
    return;
  }
  //cout<<"here dfs"<<endl;
  visited[i]=true;
  string pref="";
  pref+=a[i][1];
  pref+=+a[i][2];
  //cout<<pref<<endl;
  auto f=begs.find(pref);
  if(f!=begs.end()){
    for(int j=0;j<f->second.size();++j){
      //cout<<"neighbor of"<<i<<"is:"<<f->second[j]<<endl;
      if(visited[f->second[j]]==false)	{
	path[idx]=f->second[j];
	dfs(f->second[j],path,idx+1,visited, ans, a, begs);
      }
    }
  }
  visited[i]=false;
}
int main(){
  cin>>n;
  unordered_map< string, vector<int> > begs;
  vector<string> a(n);
  vector<int> ans(n,-1);
  vector<bool> visited(n);
  vector<int> path(n);
  for(int i=0;i<n;++i){
    cin>>a[i];
    string pref="";
    pref+=a[i][0];
    pref+=a[i][1];
    begs[pref].push_back(i);
  }
  //cout<<"here"<<endl;
  for(int i=0;i<n;++i){
    path[0]=i;
    dfs(i,path, 1, visited, ans, a, begs);
  }
  //cout<<"dfs done"<<endl;
  if(ans[n-1]==-1)
    cout<<"NO\n";
  else{
    cout<<"YES\n";
    for(int i=0;i<ans.size();++i){
      cout<<a[ans[i]][0];
      if(i==n-1)
	cout<<a[ans[i]][1]<<a[ans[i]][2];
    }
    cout<<'\n';
  }
  return 0;
}