#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define ll long long
#define pb push_back
#define all(x) x.begin(),x.end()
#define f first
#define s second

using namespace __gnu_pbds;
using namespace std;
template<class T> using ordered_set=tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
template<class T1,class T2> ostream& operator<<(ostream& out,pair<T1,T2> a){out << "[" << a.f << "," << a.s << "]"; return out;}
template<class T> ostream& operator<<(ostream& out, vector<T> a){out << "{";for(auto p:a)out << p << ",";out << "}";return out;}

const int N=14;
int dp[1<<N][N];
string dodajem[1<<N][N];
pair<int,int> nxt[1<<N][N];
string razlika[N][N];
int nn;
int calc(int mask,int last)
{
    if(mask==(1<<nn)-1)
        return 0;
    if(dp[mask][last]!=-1)
        return dp[mask][last];
    dp[mask][last]=INT_MAX;
    for(int i=0;i<nn;i++)
    {
        if(mask&(1<<i))
            continue;
        int trsol=razlika[last][i].size()+calc(mask|(1<<i),i);
        if(trsol<dp[mask][last])
        {
            dp[mask][last]=trsol;
            nxt[mask][last]={mask|(1<<i),i};
            dodajem[mask][last]=razlika[last][i];
        }
    }
    return dp[mask][last];
}
bool cmp(string a,string b){
    return a.size()<b.size();
}
int Resi(int n,int k,int *l,char **A,char* s)
{
    vector<string> a(n+1," ");
    for(int i=1;i<=n;i++)
        for(int j=1;j<=l[i];j++)
            a[i]+=A[i][j];
    sort(all(a),cmp);
    for(int i=1;i<=n;i++){
        l[i]=a[i].size()-1;
        //printf("%i\n",l[i]);
    }
    //cout << a << endl;
    nn=n;
    memset(dp,-1,sizeof(dp));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j)
                continue;
            int cnt=0;
            for(int x=1;x<=l[i];x++)
            {
                if(x+l[j]-1>l[i])
                    break;
                bool moze=true;
                for(int y=1;y+x-1<=l[i]&&y<=l[j];y++)
                    if(a[i][x+y-1]!=a[j][y])
                        moze=false;
                if(moze)
                    cnt++;
                /*if(x+l[j]-1>l[i])
                    break;
                bool moze=true;
                for(int y=1;y<=l[j];y++)
                    if(a[i][x+y-1]!=a[j][y])
                        moze=false;
                if(moze)
                    cnt++;*/
            }
            /*if(cnt==1)
            {
                while(true)
                {

                }
                //printf("DA!\n");
                for(int x=1;x<=l[i];x++)
                    s[x]=A[i][x];
                return l[i];
            }*/
            if(cnt>1)
                return -1;
        }
    }
    while(true)
    {
        bool nasao=false;
        for(int i=1;i<=n;i++)
        {
            vector<string> lft,rght;
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    continue;
                for(int x=1;x<=l[j];x++)
                {
                    if(x+l[i]-1>l[j])
                        break;
                    bool moze=true;
                    for(int y=1;y<=l[i];y++)
                        if(a[j][x+y-1]!=a[i][y])
                            moze=false;
                    if(moze)
                    {
                        string le,ri;
                        for(int y=1;y<x;y++)
                            le+=a[j][y];
                        for(int y=x+l[i];y<=l[j];y++)
                            ri+=a[j][y];
                        lft.pb(le);
                        rght.pb(ri);
                        break;
                    }
                }
            }
            //cout << lft << rght << endl;
            bool ima=false;
            for(auto p:lft)
                if(p!="")
                    ima=true;
            if(!ima)
                continue;
            nasao=true;
            sort(all(lft),cmp);
            for(auto &p:lft)
                reverse(all(p));
            sort(all(rght),cmp);
            for(int i=1,n=lft.size();i<n;i++)
            {
                int b=lft[i-1].size();
                if(lft[i].substr(0,b)!=lft[i-1])
                    return -1;
            }
            for(int i=1,n=rght.size();i<n;i++)
            {
                int b=rght[i-1].size();
                if(rght[i].substr(0,b)!=rght[i-1])
                    return -1;
            }
            reverse(all(lft.back()));
            string novi=" ";
            novi+=lft.back();
            for(int j=1;j<=l[i];j++)
                novi+=a[i][j];
            novi+=rght.back();
            l[i]=novi.size()-1;
            //cout << novi << l[i] << endl;
            a[i]=novi;
        }
        if(!nasao)
            break;
    }
    /*for(int i=1;i<=n;i++)
    {
        printf("%i\n",l[i]);
        cout << a[i] << endl;
    }*/
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int x=1;x<=l[i];x++)
            {
                bool moze=true;
                for(int y=1;y+x-1<=l[i]&&y<=l[j];y++)
                    if(a[i][x+y-1]!=a[j][y])
                        moze=false;
                //printf("Gledam %i %i %i: %i\n",i,j,x,moze);
                if(moze)
                {
                    int siz=l[j]-(l[i]-x+1);
                    for(int y=l[j]-siz+1;y<=l[j];y++)
                        razlika[i-1][j-1]+=a[j][y];
                    break;
                }
                if(x==l[i])
                {
                    for(int y=1;y<=l[j];y++)
                        razlika[i-1][j-1]+=a[j][y];
                    break;
                }
            }
            //printf("%i %i: ",i,j);
            //cout << razlika[i-1][j-1] << endl;
        }
    }

    int sol=INT_MAX;
    int gde;
    for(int i=0;i<n;i++){
        int tr=l[i+1]+calc(1<<i,i);
        if(tr<sol)
        {
            sol=tr;
            gde=i;
        }
    }
    string ans;
    for(int i=1;i<=l[gde+1];i++)
        ans+=a[gde+1][i];
    pair<int,int> tr={1<<gde,gde};
    while(tr.f!=(1<<n)-1)
    {
        ans+=dodajem[tr.f][tr.s];
        tr=nxt[tr.f][tr.s];
    }
    for(int i=0;i<(int)ans.size();i++)
        s[i+1]=ans[i];
    int len=ans.size();
    //cout << ans << endl;
    for(int i=1;i<=n;i++)
    {
        int cnt=0;
        for(int x=1;x<=len;x++)
        {
            bool moze=true;
            if(x+l[i]-1>len)
                break;
            for(int y=1;y<=l[i];y++)
                if(a[i][y]!=s[x+y-1])
                    moze=false;
            if(moze)
                cnt++;
        }
        if(cnt!=1){
            //printf("%i!\n",i);
            return -1;
        }
    }
    return len;
}