Problem:
Problem G
JAG-channel II
JAG (Japan Alumni Group) is a group of $N$ members that devotes themselves to activation of the competitive programming world. The JAG staff members talk every day on the BBS called JAG-channel. There are several threads in JAG-channel and these are kept sorted by the time of their latest posts in descending order.
One night, each of the $N$ members, identified by the first $N$ uppercase letters respectively, created a thread in JAG-channel. The next morning, each of the $N$ members posted in exactly $K$ different threads which had been created last night. Since they think speed is important, they viewed the threads from top to bottom and posted in the thread immediately whenever they came across an interesting thread. Each member viewed the threads in a different period of time, that is, there was no post of other members while he/she was submitting his/her $K$ posts.
Your task is to estimate the order of the members with respect to the periods of time when members posted in the threads. Though you do not know the order of the threads created, you know the order of the posts of each member. Since the threads are always kept sorted, there may be invalid orders of the members such that some members cannot post in the top-to-bottom order of the threads due to the previous posts of other members. Find out the lexicographically smallest valid order of the members.
Input
The input consists of a single test case. The first line contains two integers separated by a space: $N$ $(4 \leq N \leq 16)$ and $K$ $(N - 3 \leq K \leq N - 1)$. Then $N$ lines of strings follow. Each of the $N$ lines consists of exactly $K$ distinct characters. The $j$-th character of the $i$-th line denotes the $j$-th thread in which the
member denoted by the $i$-th uppercase letter posted. Each thread is represented by its creator (e.g. '
B
' represents the thread created by member B, the second member).
It is guaranteed that at least one valid order exists.
Output
Display a string that consists of exactly $N$ characters in a line, which denotes the valid order in which the members posted in the threads. The $i$-th character of the output should represent the member who posted in the $i$-th period. In case there are multiple valid orders, output the lexicographically smallest one.
Sample Input 1
7 4
DEFG
FEDA
EFGB
BGEA
AGFD
DABC
CADE
Output for the Sample Input 1
ABCDEFG
Sample Input 2
4 3
CDB
DAC
BAD
ABC
Output for the Sample Input 2
DCBA
Sample Input 3
16 13
NDHPFJIBLMCGK
CMDJKPOLGIHNE
MOLBIEJFPHADN
KPNAOHBLMCGEI
FCMLBHDOANJPK
NHIGLOAPKJDMC
KMLBIPHDEOANJ
IEGCMLBOAPKJD
JNAOEDHBLMCGF
OEDHPFIBLMGKC
GMLBIFPHDNAEO
ENHGOPKJDMCAF
JKPAOBLGEIHNF
HPKFGJEIBLCOM
LBINEJDAGFKPH
FGMOCADJENIBL
Output for the Sample Input 3
PONCAKJGIEDHMFBL

Submitted solutions:

code_snippet: //ΔAIZU2693
#include<iostream>
#include<cstdio>
#include<fstream>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<bitset>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef unsigned long long LL;
typedef double DB;
const int N = 17;
const int W = N*N*N*N;
int n,k,w,o,b[N][W],c[W];
LL a[N][W];
string s;
map<LL,int> M;
int u[N],f,tot;
LL t,ans,p;
int e[N],q[1<<N];
void prt(LL x){
	int i;
	for(i=n;i--;)
		e[i]=(x&15)+'A',x>>=4;
	for(i=0;i<n;i=i+1)
		cout<<(char)e[i];
	cout<<endl;
}
LL nx(LL x){
	int i;
	LL r=t;
	for(i=n;i--;)
		e[i]=r&15,r>>=4;
	for(i=n;i--;)
		if(u[e[i]]>=2)
			r=r<<4|e[i];
	for(i=0;i<n;i=i+1)
		if(u[e[i]]<2)
			r=r<<4|e[i];
	return r;
}
void dfs1(int x,int y){
	if(x==n&&y==k){
		if(M.find(t)==M.end())
			M[t]=++w;
		a[o][M[t]]=nx(t);
		//prt(t);
		//prt(nx(t));
		return;
	}
	x++,t<<=4;
	int i;
	for(i=0;i<n;i=i+1){
		if(u[i]==2){
			if(i==s[y]){
				t^=i,u[i]=3;
				dfs1(x,y+1);
				t^=i,u[i]=2;
			}
		}
		if(!u[i]){
			t^=i,u[i]=1;
			dfs1(x,y);
			t^=i,u[i]=0;
		}
	}
	t>>=4;
}
void dfs2(int x,int y){
	if(f||t<<(x<<2)>=ans)
		return;
	if(!x){
		ans=t;
		f=1;
		return;
	}
	if(!y||q[p])
		return;
	q[p]=1;
	tot++;
	x--,t<<=4;
	int i;
	for(i=0;i<n;i=i+1){
		if(u[i]||!a[i][y])
			continue;
		u[i]=1,t^=i,p^=1<<i;
		dfs2(x,b[i][y]);
		u[i]=0,t^=i,p^=1<<i;
	}
	t>>=4;
}
int main()
{
	int i,j;
	cin>>n>>k;
	for(i=0;i<n;i=i+1){
		cin>>s;
		for(j=0;j<k;j=j+1)
			s[j]-='A';
		for(j=0;j<n;j=j+1)
			u[j]=0;
		for(j=0;j<k;j=j+1)
			u[s[j]]=2;
		t=0,o=i;
		dfs1(0,0);
	}
	for(i=0;i<n;i=i+1)
		for(j=1;j<=w;j=j+1)
			if(a[i][j])
				b[i][j]=M[a[i][j]];
	ans=-1;
	for(i=1;i<=w;i=i+1)
		c[i]=i;
	random_shuffle(c+1,c+w+1);
	for(i=1;i<=w;i=i+1){
		for(j=0;j<n;j=j+1)
			u[j]=0;
		for(j=0;j<(1<<n);j=j+1)
			q[j]=0;
		t=0,p=0,f=0;
		dfs2(n,c[i]);
		if(tot>=1e7)
			break;
	}
	prt(ans);
	return 0;
}
/*
15 12
ABCDEFGHIJKL
ABCDEFGHIJKL
ABCDEFGHIJKL
ABCDEFGHIJKL
ABCDEFGHIJKL
ABCDEFGHIJKL
ABCDEFGHIJKL
LKJIHGFEDCBA
LKJIHGFEDCBA
LKJIHGFEDCBA
LKJIHGFEDCBA
LKJIHGFEDCBA
LKJIHGFEDCBA
LKJIHGFEDCBA
LKJIHGFEDCBA

9 6
ABCDEF
ABCDEF
ABCDEF
ABCDEF
FEDCBA
FEDCBA
FEDCBA
FEDCBA
FEDCBA

*/
accuracy: 1
time_ms: 890
memory_kb: 21252
final_rank: 8

code_snippet: //ΔAIZU2693
#include<iostream>
#include<cstdio>
#include<fstream>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<bitset>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef unsigned long long LL;
typedef double DB;
const int N = 17;
const int W = N*N*N*N;
int n,k,w,o,b[N][W];
LL a[N][W];
string s;
map<LL,int> M;
set<int> vis;
int u[N],p;
LL t;
int e[N];
void prt(LL x){
	int i;
	for(i=n;i--;)
		e[i]=(x&15)+'A',x>>=4;
	for(i=0;i<n;i=i+1)
		cout<<(char)e[i];
	cout<<endl;
}
LL nx(LL x){
	int i;
	LL r=t;
	for(i=n;i--;)
		e[i]=r&15,r>>=4;
	for(i=n;i--;)
		if(u[e[i]]>=2)
			r=r<<4|e[i];
	for(i=0;i<n;i=i+1)
		if(u[e[i]]<2)
			r=r<<4|e[i];
	return r;
}
void dfs1(int x,int y){
	if(x==n&&y==k){
		if(M.find(t)==M.end())
			M[t]=++w;
		a[o][M[t]]=nx(t);
		//prt(t);
		//prt(nx(t));
		return;
	}
	x++,t<<=4;
	int i;
	for(i=0;i<n;i=i+1){
		if(u[i]==2){
			if(i==s[y]){
				t^=i,u[i]=3;
				dfs1(x,y+1);
				t^=i,u[i]=2;
			}
		}
		if(!u[i]){
			t^=i,u[i]=1;
			dfs1(x,y);
			t^=i,u[i]=0;
		}
	}
	t>>=4;
}
void dfs2(int x,int y){
	if(!x){
		prt(t);
		exit(0);
	}
	if(!y)
		return;
	if(vis.find(y<<n|p)!=vis.end())
		return;
	vis.insert(y<<n|p);
	x--,t<<=4;
	int i;
	for(i=0;i<n;i=i+1){
		if(u[i]||!a[i][y])
			continue;
		u[i]=1,t^=i,p^=1<<i;
		dfs2(x,b[i][y]);
		u[i]=0,t^=i,p^=1<<i;
	}
	t>>=4;
}
int main()
{
	int i,j;
	cin>>n>>k;
	for(i=0;i<n;i=i+1){
		cin>>s;
		for(j=0;j<k;j=j+1)
			s[j]-='A';
		for(j=0;j<n;j=j+1)
			u[j]=0;
		for(j=0;j<k;j=j+1)
			u[s[j]]=2;
		t=0,o=i;
		dfs1(0,0);
	}
	for(i=0;i<n;i=i+1)
		for(j=1;j<=w;j=j+1)
			if(a[i][j])
				b[i][j]=M[a[i][j]];
	for(i=1;i<=w;i=i+1){
		for(j=0;j<n;j=j+1)
			u[j]=0;
		t=0,p=0;
		dfs2(n,i);
	}
	return 0;
}
/*
15 14
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
NMLKJIHGFEDCBA
NMLKJIHGFEDCBA
NMLKJIHGFEDCBA
NMLKJIHGFEDCBA
NMLKJIHGFEDCBA
NMLKJIHGFEDCBA
NMLKJIHGFEDCBA
NMLKJIHGFEDCBA

*/
accuracy: 0.07142857142857142
time_ms: 20
memory_kb: 23524
final_rank: 19

code_snippet: // AOJ #2693
// JAG-channel II 2025.2.11

#include <bits/stdc++.h>
using namespace std;
 
int N, K;
vector<string> posts;
string allMembers;
 
pair<bool,string> simulateFinal(const string &initState, const string &target, int K) {
    vector<char> board(initState.begin(), initState.end());
    int p = 0;
    for (char y : target) {
        while(p < (int)board.size() && board[p] != y)
            p++;
        if(p == (int)board.size()) return {false, ""};
        char found = board[p];
        board.erase(board.begin()+p);
        board.insert(board.begin(), found);
        p++;
    }
    string front = "";
    for (int i = 0; i < K; i++) front.push_back(board[i]);
    string revTarget = target;
    reverse(revTarget.begin(), revTarget.end());
    string tail = "";
    for (int i = K; i < (int)board.size(); i++)
        tail.push_back(board[i]);
    return {true, tail};
}
 
void genPermutations(vector<char> &arr, int start, vector<string> &perms) {
    if(start == (int)arr.size()){
        string s(arr.begin(), arr.end());
        perms.push_back(s);
        return;
    }
    for (int i = start; i < (int)arr.size(); i++){
        swap(arr[start], arr[i]);
        genPermutations(arr, start+1, perms);
        swap(arr[start], arr[i]);
    }
}
 
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    cin >> N >> K;
    posts.resize(N);
    for (int i = 0; i < N; i++) cin >> posts[i];
    allMembers = "";
    for (int i = 0; i < N; i++) allMembers.push_back('A' + i);
 
    vector<vector<string>> extraPerms(N);
    vector<unordered_map<string,int>> extraIndex(N);
    for (int i = 0; i < N; i++){
        unordered_set<char> used;
        for (char c : posts[i]) used.insert(c);
        vector<char> extras;
        for (char c : allMembers) {
            if(used.find(c) == used.end()) extras.push_back(c);
        }
        vector<string> perms;
        if(extras.empty()) perms.push_back("");
        else genPermutations(extras, 0, perms);
        sort(perms.begin(), perms.end());
        extraPerms[i] = perms;
        for (int j = 0; j < (int)perms.size(); j++)
            extraIndex[i][perms[j]] = j;
    }
 
    vector<vector<vector<int>>> nextTrans(N);
    for (int i = 0; i < N; i++){
        int sz = extraPerms[i].size();
        nextTrans[i].resize(sz, vector<int>(N, -1));
        string rev = posts[i];
        reverse(rev.begin(), rev.end());
        for (int qi = 0; qi < sz; qi++){
            string boardState = rev + extraPerms[i][qi];
            for (int j = 0; j < N; j++){
                if(i == j) continue;
                auto simRes = simulateFinal(boardState, posts[j], K);
                if(!simRes.first) nextTrans[i][qi][j] = -1;
                else {
                    string tail = simRes.second;
                    if(extraIndex[j].find(tail) != extraIndex[j].end())
                        nextTrans[i][qi][j] = extraIndex[j][tail];
                    else nextTrans[i][qi][j] = -1;
                }
            }
        }
    }
 
    const string INF = string(100, '{');
    int fullMask = (1 << N) - 1;
    vector<vector<vector<string>>> dp(1 << N, vector<vector<string>>(N));
    for (int i = 0; i < N; i++){
        int mask = (1 << i);
        int sz = extraPerms[i].size();
        dp[mask][i].resize(sz, INF);
        for (int qi = 0; qi < sz; qi++)
            dp[mask][i][qi] = string(1, 'A' + i);
    }
 
    for (int mask = 0; mask < (1 << N); mask++){
        for (int i = 0; i < N; i++){
            if (!(mask & (1 << i))) continue;
            int sz = dp[mask][i].size();
            for (int qi = 0; qi < sz; qi++){
                string cur = dp[mask][i][qi];
                if(cur == INF) continue;
                for (int j = 0; j < N; j++){
                    if(mask & (1 << j)) continue;
                    int nxtIndex = nextTrans[i][qi][j];
                    if(nxtIndex == -1) continue;
                    int newMask = mask | (1 << j);
                    string candidate = cur + char('A' + j);
                    if(dp[newMask][j].size() < extraPerms[j].size())
                        dp[newMask][j].resize(extraPerms[j].size(), INF);
                    if(candidate < dp[newMask][j][nxtIndex])
                        dp[newMask][j][nxtIndex] = candidate;
                }
            }
        }
    }
 
    string ans = INF;
    for (int i = 0; i < N; i++){
        for (auto &s : dp[fullMask][i]){
            if(s < ans) ans = s;
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 157544
final_rank: 12

code_snippet: // AOJ #2693
// JAG-channel II 2025.2.11

#include <bits/stdc++.h>
using namespace std;
 
 
bool simulateSession(const string &initState, const string &target) {
    vector<char> board(initState.begin(), initState.end());
    int p = 0;
    for (char y : target) {
        while(p < (int)board.size() && board[p] != y) p++;
        if(p == (int)board.size()) return false;
        char found = board[p];
        board.erase(board.begin() + p);
        board.insert(board.begin(), found);
        p++;
    }
    return true;
}
 
 
void genPermutations(vector<char>& arr, int start, vector<string> &perms) {
    if(start == (int)arr.size()){
        string s(arr.begin(), arr.end());
        perms.push_back(s);
        return;
    }
    for (int i = start; i < (int)arr.size(); i++){
        swap(arr[start], arr[i]);
        genPermutations(arr, start+1, perms);
        swap(arr[start], arr[i]);
    }
}
 
 
bool validTransition(const string &prevSeq, const string &nextSeq, const string &allMembers) {
    unordered_set<char> U;
    for (char c : prevSeq) U.insert(c);
    vector<char> extra;
    for (char c : allMembers)
        if (U.find(c) == U.end()) extra.push_back(c);
    string R = prevSeq;
    reverse(R.begin(), R.end());
 
    vector<string> qPerms;
    if(!extra.empty()) genPermutations(extra, 0, qPerms);
    else qPerms.push_back("");
 
    for(auto &q : qPerms){
        string boardState = R + q;
        if(simulateSession(boardState, nextSeq)) return true;
    }
    return false;
}
 
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N, K;
    cin >> N >> K;
    vector<string> posts(N);
    for (int i = 0; i < N; i++) cin >> posts[i];
 
    string allMembers = "";
    for (int i = 0; i < N; i++) allMembers.push_back('A' + i);
 
    vector<vector<bool>> valid(N, vector<bool>(N, false));
    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++){
            if(i == j) continue;
            bool poss = validTransition(posts[i], posts[j], allMembers);
            valid[i][j] = poss;
        }
    }
 
    const int fullMask = (1 << N) - 1;
    vector<vector<string>> dp(1 << N, vector<string>(N, "{"));
    for (int i = 0; i < N; i++){
        int m = (1 << i);
        string s;
        s.push_back('A' + i);
        dp[m][i] = s;
    }
 
    for (int mask = 0; mask < (1 << N); mask++){
        for (int last = 0; last < N; last++){
            if(dp[mask][last] == "{") continue;
            for (int j = 0; j < N; j++){
                if(mask & (1 << j)) continue;
                if(!valid[last][j]) continue;
                int newMask = mask | (1 << j);
                string candidate = dp[mask][last] + char('A' + j);
                if(candidate < dp[newMask][j]) dp[newMask][j] = candidate;
            }
        }
    }
 
    string ans = "{";
    for (int i = 0; i < N; i++){
        if(dp[fullMask][i] < ans) ans = dp[fullMask][i];
    }
    cout << ans << endl;
    return 0;
}
accuracy: 0.30952380952380953
time_ms: 20
memory_kb: 38436
final_rank: 17

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rrep(i, a, b) for (ll i = (ll)(b)-1; i >= (ll)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int N, K;
    cin >> N >> K;
    vector<string> S(N);
    rep(i,0,N) cin >> S[i];
    vector used(N, vector<bool>(N,false));
    rep(i,0,N) {
        rep(j,0,K) {
            used[i][S[i][j]-'A'] = true;
        }
    }
    vector<map<string,string>> DP(1<<N);
    auto DFS = [&](auto self, int X, string Cur) -> string {
        if (X == (1<<N)-1) return "";
        if (DP[X].count(Cur)) return DP[X][Cur];
        string Ret = "$";
        rep(i,0,N) {
            if (X & (1<<i)) continue;
            int it = 0;
            rep(j,0,N) {
                if (Cur[j] == S[i][it]) it++;
                if (it == K) break;
            }
            if (it != K) continue;
            string Next = S[i];
            reverse(ALL(Next));
            rep(j,0,N) {
                if (!used[i][Cur[j]-'A']) Next += Cur[j];
            }
            string Ret2 = self(self,X|(1<<i),Next);
            if (Ret2 == "$") continue;
            Ret2 = (char)('A'+i) + Ret2;
            if (Ret == "$") Ret = Ret2;
            else chmin(Ret, Ret2);
        }
        return DP[X][Cur] = Ret;
    };
    string ANS = "$";
    rep(i,0,N) {
        string Cur = S[i];
        reverse(ALL(Cur));
        string Rem = "";
        rep(j,0,N) {
            if (!used[i][j]) Rem += (char)('A'+j);
        }
        do {
            string Next = Cur + Rem;
            string Ret = DFS(DFS,1<<i,Next);
            if (Ret == "$") continue;
            Ret = (char)('A'+i) + Ret;
            if (ANS == "$") ANS = Ret;
            else chmin(ANS, Ret);
        } while(next_permutation(ALL(Rem)));
    }
    cout << ANS << endl;
}
accuracy: 1
time_ms: 150
memory_kb: 28624
final_rank: 3

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

/*
0:012
1:102
2:021
3:120
4:201
5:210
*/

int sz[3] = {1,2,6};

int vv[6][3] = {
    {0,1,2},
    {1,0,2},
    {0,2,1},
    {1,2,0},
    {2,0,1},
    {2,1,0}
};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,k; cin >> n >> k;
    vector<string> s(n);
    for(int i=0;i<n;i++){
        cin >> s[i];
    }
    vector<map<pair<int,int>,int>> ok(n);
    for(int i=0;i<n;i++){
        for(int j=0;j<sz[n-k-1];j++){
            string t = s[i];
            reverse(t.begin(), t.end());
            int bit = 0;
            for(char c:s[i]){
                bit |= (1<<(c-'A'));
            }
            string r = "";
            for(int k=0;k<n;k++){
                if((1<<k)&bit) continue;
                r += (char)('A'+k);
            }
            for(int k=0;k<r.size();k++){
                t += r[vv[j][k]];
            }
            for(int k=0;k<n;k++){
                int a = 0;
                int b = 0;
                while(a < t.size() and b < s[k].size()){
                    if(t[a] == s[k][b]){
                        b++;
                    }
                    a++;
                }
                if(s[k].size() == b){
                    bit = 0;
                    for(char c:s[k]){
                        bit |= (1<<(c-'A'));
                    }
                    r = "";
                    for(char c:t){
                        if((1<<(c-'A'))&bit) continue;
                        r += c;
                    }
                    vector<int> v(r.size());
                    for(int p=0;p<v.size();p++){
                        for(int q=0;q<v.size();q++){
                            if(r[p] > r[q]) v[p]++;
                        }
                    }
                    for(int p=0;p<6;p++){
                        bool okok = true;
                        for(int q=0;q<v.size();q++){
                            if(vv[p][q] != v[q]) okok = false;
                        }
                        if(okok){
                            ok[k][{i,j}] = p;
                            // cout << vv[p][0] << vv[p][1] << vv[p][2] << endl;
                            // cout << i << " " << j << " " << k << " " << p << " " << r << " " << v[0] << v[1] << v[2] << endl;
                            break;
                        }
                    }
                }
                else{
                    ok[k][{i,j}] = -1;
                }
            }
        }
    }
    map<pair<int,pair<int,int>>, string> mp;
    auto dfs = [&](auto dfs,int bit,int last,int sta)->string{
        if(mp.find({bit,{last,sta}}) != mp.end()){
            return mp[{bit,{last,sta}}];
        }
        string res = "Z";
        for(int i=0;i<n;i++){
            if((1<<i)&bit) continue;
            if(ok[i][{last,sta}] != -1){
                string rr = "";
                rr += (char)('A'+i);
                rr += dfs(dfs,bit+(1<<i),i,ok[i][{last,sta}]);
                res = min(res,rr);
            }
        }
        mp[{bit,{last,sta}}] = res;
        return res;
    }; 
    string res = "Z";
    for(int i=0;i<n;i++){
        for(int j=0;j<sz[n-k-1];j++){
            string t = "";
            t += (char)('A'+i);
            t += dfs(dfs,1<<i,i,j);
            if(t.size() == n+1){
                res = min(res, t);
            }
        }
    }
    res.pop_back();
    cout << res << endl;
}
accuracy: 1
time_ms: 780
memory_kb: 62600
final_rank: 9

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
// #include <atcoder/convolution>
// using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 1020000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
//const int mod = 1e9 + 7;
const int mod = 998244353;

unsigned long long dp[1<<16][16][6];
bool ok[1<<16][16][6];

int main(){
    int n,k; cin >> n >> k;
    vs s(n); rep(i,n) cin >> s[i];
    vs rs(n);
    rep(i,n){
        rs[i] = s[i];
        reverse(all(rs[i]));
    }
    rep(i,1<<n) rep(j,n) rep(l,6) dp[i][j][l] = -1;
    rep(i,n) rep(j,6){
        dp[1<<i][i][j] = i;
        ok[1<<i][i][j] = true;
    }
    vl cnt(n,0);
    rep(bit,1<<n) rep(i,n){
        int now = 0;
        rep(j,n) cnt[j] = 0;
        rep(j,k) cnt[s[i][j]-'A']++;
        string t;
        rep(j,n) if(cnt[j] == 0) t += (char)(j+'A');
        do{
            if(!ok[bit][i][now]){
                now++; continue;
            }
            rep(j,n){
                if(bit>>j & 1) continue;
                string u = rs[i] + t;
                int ptr = 0;
                string v;
                rep(l,n){
                    if(ptr < k && u[l] == s[j][ptr]) ptr++;
                    else v += u[l];
                }
                if(ptr != k) continue;
                string vv = v;
                sort(all(vv));
                int nxt = 0;
                do{
                    if(v == vv) break;
                    nxt++;
                }while(next_permutation(all(vv)));
                if(chmin(dp[bit|1<<j][j][nxt], dp[bit][i][now]*16 + j)){
                    ok[bit|1<<j][j][nxt] = true;
                }
            }
            now++;
        }while(next_permutation(all(t)));
    }
    unsigned long long val = -1;
    rep(i,n){
        rep(j,6){
            chmin(val, dp[(1<<n)-1][i][j]);
        }
    }
    string ans;
    rep(i,n){
        ans += (char)(val%16+'A');
        val /= 16;
    }
    reverse(all(ans));
    cout << ans << endl;
}
accuracy: 1
time_ms: 440
memory_kb: 58680
final_rank: 4

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

//constexpr long long MOD = 1000000007;
constexpr long long MOD = 998244353;
constexpr double EPS = 1e-8;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> N >> K;
	vector<string>s(N);
	for (auto& i : s)cin >> i;
	set<char>st;
	for (int i = 0; i < N; i++) {
		st.insert('A' + i);
	}
	vector amari(N, vector(0, string()));
	for (int i = 0; i < N; i++) {
		auto t = st;
		for (auto j : s[i])t.erase(j);
		string u;
		for (auto j : t) {
			u.push_back(j);
		}
		do {
			amari[i].push_back(u);
		} while (next_permutation(u.begin(), u.end()));
	}
	vector dp(vector(1 << N, vector(N, vector(6, vector<int>()))));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < amari[0].size(); j++) {
			dp[1 << i][i][j].push_back(i);
		}
	}
	vector ok(N, vector(amari[0].size(), vector(N, -1)));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < amari[0].size(); j++) {
			string box = s[i];
			reverse(box.begin(), box.end());
			for (auto k : amari[i][j])box.push_back(k);
			for (int k = 0; k < N; k++) {
				int idx = 0;
				string a;
				for (int l = 0; l < K; l++) {
					if (l)idx++;
					while (idx < N && box[idx] != s[k][l]) {
						a.push_back(box[idx]);
						idx++;
					}
				}
		//		cout << i << " " << j << " " << k << " " << a << endl;
				if (idx < N) {
					for (int l = idx + 1; l < N; l++) {
						a.push_back(box[l]);
					}
					for (int l = 0; l < amari[0].size(); l++) {
					//	cout << i << " " << j << " " << k << " " << l << endl;
					//	cout << a.substr(a.size() - amari[0][0].size(), amari[0][0].size()) << endl;
						if (a.substr(a.size() - amari[0][0].size(), amari[0][0].size()) == amari[k][l]) {
							ok[i][j][k] = l;
					//		cout << i << " " << j << " " << k << " " << l << endl;
						}
					}
				}
			}
		}
	}
	for (int i = 1; i < 1 << N; i++) {
		for (int j = 0; j < N; j++) {
			if (i >> j & 1) {
				for (int k = 0; k < amari[0].size(); k++) {
					if (dp[i][j][k].empty())continue;
					for (int l = 0; l < N; l++) {
						if (i >> l & 1)continue;
						if (ok[j][k][l] < 0)continue;
						if (dp[i | (1 << l)][l][ok[j][k][l]].empty()) {
							dp[i | (1 << l)][l][ok[j][k][l]] = dp[i][j][k];
							dp[i | (1 << l)][l][ok[j][k][l]].push_back(l);
						}
						else {
							dp[i | (1 << l)][l][ok[j][k][l]] = min(dp[i][j][k], dp[i | (1 << l)][l][ok[j][k][l]]);
							if (dp[i | (1 << l)][l][ok[j][k][l]].back() != l) {
								dp[i | (1 << l)][l][ok[j][k][l]].push_back(l);
							}
						}
					}
				}
			}
		}
	}
	vector<int>ans;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < amari[0].size(); j++) {
			if (dp.back()[i][j].size()) {
				if (ans.empty()) {
					ans = dp.back()[i][j];
				}
				ans = min(ans, dp.back()[i][j]);
			}
		}
	}
	for (auto i : ans)cout << char('A' + i);
	cout << endl;
}
accuracy: 1
time_ms: 230
memory_kb: 236208
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
int main(){
  int N, K;
  cin >> N >> K;
  vector<string> S(N);
  for (int i = 0; i < N; i++){
    cin >> S[i];
  }
  int F = 1;
  for (int i = 1; i <= N - K; i++){
    F *= i;
  }
  vector<vector<string>> S2(N);
  for (int i = 0; i < N; i++){
    vector<bool> used(N, false);
    for (int j = 0; j < K; j++){
      used[S[i][j] - 'A'] = true;
    }
    for (int j = 0; j < N; j++){
      if (!used[j]){
        S[i] += (char) ('A' + j);
      }
    }
    while (true){
      S2[i].push_back(S[i]);
      if (!next_permutation(S[i].begin() + K, S[i].end())){
        break;
      }
    }
  }
  vector<vector<vector<vector<bool>>>> ok(N, vector<vector<vector<bool>>>(F, vector<vector<bool>>(N, vector<bool>(F, true))));
  for (int i = 0; i < N; i++){
    for (int j = 0; j < F; j++){
      for (int k = 0; k < N; k++){
        for (int l = 0; l < F; l++){
          string s = S2[i][j];
          reverse(s.begin(), s.begin() + K);
          vector<int> p(N, -1);
          for (int m = 0; m < N; m++){
            for (int n = 0; n < N; n++){
              if (s[m] == S2[k][l][n]){
                p[n] = m;
              }
            }
          }
          for (int m = 0; m < K - 1; m++){
            if (p[m] > p[m + 1]){
              ok[i][j][k][l] = false;
            }
          }
          for (int m = K; m < N - 1; m++){
            if (p[m] > p[m + 1]){
              ok[i][j][k][l] = false;
            }
          }
        }
      }
    }
  }
  vector<vector<vector<string>>> dp(1 << N, vector<vector<string>>(N, vector<string>(F, "Z")));
  for (int i = 0; i < N; i++){
    for (int j = 0; j < F; j++){
      dp[1 << i][i][j] = string(1, (char) ('A' + i));
    }
  }
  for (int i = 1; i < (1 << N); i++){
    for (int j = 0; j < N; j++){
      for (int k = 0; k < F; k++){
        if (dp[i][j][k] != "Z"){
          for (int l = 0; l < N; l++){
            if ((i >> l & 1) == 0){
              for (int m = 0; m < F; m++){
                if (ok[j][k][l][m]){
                  string s = dp[i][j][k] + (char) ('A' + l);
                  int i2 = i + (1 << l);
                  dp[i2][l][m] = min(dp[i2][l][m], s);
                }
              }
            }
          }
        }
      }
    }
  }
  string ans = "Z";
  for (int i = 0; i < N; i++){
    for (int j = 0; j < F; j++){
      ans = min(ans, dp[(1 << N) - 1][i][j]);
    }
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 370
memory_kb: 127792
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=100005,INF=1<<30;
string dp[1<<16][16][6];
int can[16][6][16];

string rev(string A){
    reverse(all(A));
    return A;
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    memset(can,-1,sizeof(can));
    
    int N,K;cin>>N>>K;
    vector<string> S(N);
    vector<vector<string>> state(N,vector<string>(6));
    for(int i=0;i<N;i++){
        cin>>S[i];
        vector<int> deta(N);
        for(char c:S[i]) deta[c-'A']=1;
        string rem;
        for(int j=0;j<N;j++){
            if(deta[j]==0) rem+=char('A'+j);
        }
        int t=0;
        do{
            state[i][t]=rev(S[i])+rem;
            t++;
        }while(next_permutation(all(rem)));
    }
    
    for(int i=0;i<N;i++){
        if(K==N-1) dp[(1<<i)][i][0]=char('A'+i);
        if(K==N-2){
            for(int j=0;j<2;j++) dp[(1<<i)][i][j]=char('A'+i);
        }
        if(K==N-3){
            for(int j=0;j<6;j++) dp[(1<<i)][i][j]=char('A'+i);
        }
    }
    
    for(int i=0;i<N;i++){
        for(int j=0;j<6;j++){
            string last=state[i][j];
            if(si(last)==0) continue;
            for(int k=0;k<N;k++){
                vector<int> when(K);
                for(int l=0;l<K;l++){
                    for(int x=0;x<N;x++){
                        if(S[k][l]==last[x]) when[l]=x;
                    }
                }
                bool ok=true;
                for(int l=0;l+1<K;l++){
                    if(when[l]>when[l+1]) ok=false;
                }
                
                if(!ok) continue;
                
                string nex=rev(S[k]);
                for(int x=0;x<N;x++){
                    bool check=false;
                    for(int l=0;l<K;l++){
                        if(last[x]==nex[l]) check=true;
                    }
                    if(!check) nex+=last[x];
                }
                
                for(int l=0;l<6;l++) if(nex==state[k][l]) can[i][j][k]=l;
            }
        }
    }
    
    for(int bit=0;bit<(1<<N);bit++){
        for(int i=0;i<N;i++){
            if(!(bit&(1<<i))) continue;
            for(int j=0;j<6;j++){
                if(si(dp[bit][i][j])!=__builtin_popcount(bit)) continue;
                
                string last=state[i][j];
                
                for(int to=0;to<N;to++){
                    if(bit&(1<<to)) continue;
                    
                    if(can[i][j][to]==-1) continue;
                    
                    if(si(dp[bit|(1<<to)][to][can[i][j][to]])==0||chmin(dp[bit|(1<<to)][to][can[i][j][to]],dp[bit][i][j]+char('A'+to))){
                        dp[bit|(1<<to)][to][can[i][j][to]]=dp[bit][i][j]+char('A'+to);
                    }
                }
            }
        }
    }
    
    string ans="Z";
    
    for(int i=0;i<N;i++){
        for(int j=0;j<6;j++){
            if(si(dp[(1<<N)-1][i][j])==N) chmin(ans,dp[(1<<N)-1][i][j]);
        }
    }
    
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 110
memory_kb: 200096
final_rank: 13

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
#include <set>
#include <iomanip>
#include <queue>
#include <string>
#include <map>
#include <fstream>
#include <cassert>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>
#include <random>
#include <sstream>
#include <bitset>

static std::vector<std::vector<char>> members;
static std::vector<std::vector<std::vector<int>>> cache;
int to_int(const std::vector<int>& rest) {
	auto perm = rest; std::sort(perm.begin(), perm.end());
	for (auto i = 0;; ++i) {
		bool equal{ true };
		for (auto j = 0; j < rest.size(); ++j) {
			if (rest[j] != perm[j]) {
				equal = false;
				break;
			}
		}
		if (equal) return i;
		std::next_permutation(perm.begin(), perm.end());
	}
}
bool has_cache(const int current, const int used, const std::vector<int>& rest) {
	return cache[current][used][to_int(rest)] != -2;
}
int read_cache(const int current, const int used, const std::vector<int>& rest) {
	return cache[current][used][to_int(rest)];
}
void set_cache(const int current, const int used, const std::vector<int>& rest, const int result) {
	cache[current][used][to_int(rest)] = result;
}
bool can_move(const int current, const int next, const std::vector<int>& rest) {
	static std::vector<int> rank = std::vector<int>(members.size(), 0);
	for (auto i = 0; i < members[current].size(); ++i) {
		rank[members[current][i]] = members[current].size() - i - 1;
	}
	for (auto i = 0; i < rest.size(); ++i) {
		rank[rest[i]] = members[current].size() + i;
	}
	for (auto i = 1; i < members[next].size(); ++i) {
		if (rank[members[next][i]] < rank[members[next][i - 1]]) return false;
	}
	return true;
}
std::vector<int> next_state(const int current, const int next, const std::vector<int>& rest) {
	static std::vector<int> rank = std::vector<int>(members.size(), 0);
	for (auto i = 0; i < members[current].size(); ++i) {
		rank[members[current][i]] = members[current].size() - i - 1;
	}
	for (auto i = 0; i < rest.size(); ++i) {
		rank[rest[i]] = members[current].size() + i;
	}
	std::vector<int> result; result.reserve(rest.size());
	for (const auto m : members[next]) rank[m] = -1;
	for (auto i = 0; i < rank.size(); ++i) {
		if (rank[i] >= 0) {
			result.push_back(i);
		}
	}
	std::sort(result.begin(), result.end(), [](const int i, const int j) {return rank[i] < rank[j]; });
	return result;
}
int can_make(const int current, const int used, std::vector<int> rest) {
	if (has_cache(current, used, rest)) return read_cache(current, used, rest);
	if (used + 1 == (1 << members.size())) return members.size();
	for (auto next = 0; next < members.size(); ++next) {
		if (((used >> next) & 1) == 0 && can_move(current, next, rest)) {
			const auto succ = can_make(next, used | (1 << next), next_state(current, next, rest));
			if (succ >= 0) {
				set_cache(current, used, rest, next);
				return next;
			}
		}
	}
	set_cache(current, used, rest, -1);
	return -1;
}
std::string min_order(const int current, const int used, std::vector<int> rest) {
	if (used + 1 == (1 << members.size())) return std::string(1, (char)current + 'A');
	const auto next = can_make(current, used, rest);
	auto succ = min_order(next, used | (1 << next), next_state(current, next, rest));
	succ.insert(succ.begin(), (char)current + 'A');
	return succ;
}
std::string min_order(const int start) {
	std::vector<bool> used(members.size());
	for (const auto a : members[start]) used[a] = true;
	std::vector<int> rest;
	for (auto i = 0; i < used.size(); ++i) {
		if (!used[i]) rest.push_back(i);
	}
	std::string result = "";
	do {
		if (can_make(start, 1 << start, rest) < 0) continue;
		const auto next = min_order(start, 1 << start, rest);
		if (next.empty()) continue;
		if (result.empty() || next < result) result = next;
	} while (std::next_permutation(rest.begin(), rest.end()));
	return result;
}
void initialize(const std::vector<std::string>& state) {
	cache = std::vector<std::vector<std::vector<int>>>(state.size(), std::vector<std::vector<int>>(1 << state.size(), std::vector<int>(6, -2)));
	members = std::vector<std::vector<char>>(state.size());
	for (auto i = 0; i < state.size(); ++i) {
		members[i] = std::vector<char>(state[i].size());
		for (auto j = 0; j < state[i].size(); ++j) {
			members[i][j] = state[i][j] - 'A';
		}
	}
}
std::string min_order() {
	for (auto i = 0; i < members.size(); ++i) {
		const auto res = min_order(i);
		if (res.empty()) continue;
		return res;
	}
	return "";
}

int main() {
	int n, k; std::cin >> n >> k;
	std::vector<std::string> state(n);
	for (auto& line : state) std::cin >> line;
	initialize(state);
	std::cout << min_order() << '\n';
}
accuracy: 1
time_ms: 390
memory_kb: 64108
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<int,ll> pil;
typedef pair<ll,int> pli;
#define rep(i,n) for (int i=0;i<(n);++i)
#define REP(i,n) for (int i=1;i<=(n);++i)
#define all(x) x.begin(),x.end()
#define mp make_pair
#define pb push_back
#define F first
#define S second
#define RI(x) scanf("%d",&x)
#define RII(x,y) scanf("%d%d",&x,&y)
int n,k;
string in[16],rev[16],tail[16][6];
int a[16][16];
int dp[1<<16][16][6];
int factNK;
int full;
inline int find(const string &s,int i){
	int ptr=0;
	string tmp;
	for (int j=0;j<k;++j){
		while(ptr<n&&s[ptr]!=in[i][j]){
			tmp+=s[ptr];++ptr;
		}
		++ptr;
	}
	if (ptr>n) return -1;
	while(ptr<n) tmp+=s[ptr],++ptr;
	//cerr<<s<<' '<<i<<' '<<tmp<<endl;
	rep(id,factNK) if (tail[i][id]==tmp) return id;
}
inline bool DP(int mask,int i,int j){
	if (mask==full) return 1;
	else if (dp[mask][i][j]!=-1) return dp[mask][i][j];
	int &res=dp[mask][i][j];res=0;
	string cur=rev[i]+tail[i][j];
	for (int nxt=0;nxt<n;++nxt) if ((!(mask&(1<<nxt)))){
		int recv=find(cur,nxt);
		if (recv!=-1) res|=DP(mask|(1<<nxt),nxt,recv);
	}
	//cerr<<mask<<' '<<i<<' '<<res<<endl;
	return res;
}
bool seen[16];
string ans,tmp;
inline void getAns(int mask,int i,int j){
	if (mask==full){
		tmp.pb(char('A'+i));return;
	}
	string cur=rev[i]+tail[i][j];
	for (int nxt=0;nxt<n;++nxt) if (!(mask&(1<<nxt))){
		int recv=find(cur,nxt);
		if (recv!=-1&&DP(mask|(1<<nxt),nxt,recv)){
			tmp.pb(char('A'+i));getAns(mask|(1<<nxt),nxt,recv);return;
		}
	}
}
inline void update(){
	if (ans.empty()) ans=tmp;
	rep(i,n) if (ans[i]!=tmp[i]){
		if (ans[i]>tmp[i]) ans=tmp;
		return;
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>k;
	if (k==n-1) factNK=1;
	else if (k==n-2) factNK=2;
	else factNK=6;
	rep(i,n) cin>>in[i];
	rep(i,n){
		rev[i].resize(k);
		rep(j,k) rev[i][j]=in[i][k-j-1];
	}
	rep(i,n){
		memset(seen,0,sizeof(seen));
		rep(j,k) seen[in[i][j]-'A']=1;
		rep(c,n) if (!seen[c]) tail[i][0]+=char(c+'A');
		if (k==n-2){
			tail[i][1]=tail[i][0];swap(tail[i][1][0],tail[i][1][1]);
		}
		else if (k==n-3){
			tail[i][1]=tail[i][0];swap(tail[i][1][1],tail[i][1][2]);
			tail[i][2]=tail[i][0];swap(tail[i][2][0],tail[i][2][1]);
			tail[i][3]=tail[i][2];swap(tail[i][3][1],tail[i][3][2]);
			tail[i][4]=tail[i][2];swap(tail[i][4][0],tail[i][4][2]);
			tail[i][5]=tail[i][4];swap(tail[i][5][1],tail[i][5][2]);
		}
	}
	//rep(i,n) rep(j,k) a[i][j]=in[i][j]-'A';
	full=(1<<n)-1;
	memset(dp,-1,sizeof(dp));
	//rep(i,n) cerr<<rev[i]<<endl;
	//rep(i,n) cerr<<tail[i][0]<<endl;
	rep(i,n){
		rep(j,factNK){
			tmp.clear();
			getAns(1<<i,i,j);
			if (!tmp.empty()) update();
		}
		if (!ans.empty()){
			cout<<ans<<endl;return 0;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 1150
memory_kb: 27828
final_rank: 10

code_snippet: #include<iostream>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
int N,K;
int s[16][16];
vector<pair<int,int> >G[16][6],RG[16][6];
map<vector<int>,int>order;
bool dp[16][6][1<<16];
main()
{
	cin>>N>>K;
	for(int i=0;i<N;i++)
	{
		string t;cin>>t;
		for(int j=0;j<K;j++)s[i][j]=t[j]-'A';
	}
	for(int i=0;i<N;i++)
	{
		int usd=0;
		for(int j=0;j<K;j++)usd|=1<<s[i][j];
		vector<int>rest;
		for(int j=0;j<N;j++)if(!(usd>>j&1))rest.push_back(j);
		int cnt=0;
		do{
			order[rest]=cnt++;
		}while(next_permutation(rest.begin(),rest.end()));
	}
	for(int i=0;i<N;i++)
	{
		int usd=0;
		for(int j=0;j<K;j++)usd|=1<<s[i][j];
		vector<int>rest;
		for(int j=0;j<N;j++)if(!(usd>>j&1))rest.push_back(j);
		do{
			int oid=order[rest];
			vector<int>now;
			for(int j=K;j--;)now.push_back(s[i][j]);
			for(int id:rest)now.push_back(id);
			for(int j=0;j<N;j++)if(i!=j)
			{
				int id=0;
				bool ok=true;
				vector<int>nr;
				for(int k=0;k<K;k++)
				{
					while(id<N&&now[id]!=s[j][k])
					{
						nr.push_back(now[id++]);
					}
					if(id==N)
					{
						ok=false;
						break;
					}
					id++;
				}
				if(!ok)continue;
				while(id<N)nr.push_back(now[id++]);
				G[j][order[nr]].push_back(make_pair(i,oid));
				RG[i][oid].push_back(make_pair(j,order[nr]));
			}
		}while(next_permutation(rest.begin(),rest.end()));
	}
	int LIM=1;
	for(int i=1;i<=N-K;i++)LIM*=i;
	for(int i=0;i<N;i++)for(int j=0;j<LIM;j++)dp[i][j][1<<i]=true;
	for(int i=1;i<1<<N;i++)for(int u=0;u<N;u++)if(i>>u&1)
	{
		for(int v=0;v<LIM;v++)if(dp[u][v][i])
		{
			for(pair<int,int>e:G[u][v])
			{
				int nu=e.first;
				if(i>>nu&1)continue;
				dp[nu][e.second][i|1<<nu]=true;
			}
		}
	}
	string ans="~";
	for(int i=0;i<N;i++)for(int j=0;j<LIM;j++)
	{
		int st=i,sj=j;
		int vis=(1<<N)-1;
		if(!dp[i][j][vis])continue;
		vis^=1<<i;
		string now="";
		now+=i+'A';
		while(vis)
		{
			for(pair<int,int>e:RG[st][sj])
			{
				int nu=e.first;
				if(!(vis>>nu&1))continue;
				if(dp[nu][e.second][vis])
				{
					now+=(char)(nu+'A');
					st=nu;
					sj=e.second;
					vis^=1<<nu;
					break;
				}
			}
		}
		if(ans>now)ans=now;
	}
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 8672
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int N=18;
int n,m,r,dp[1<<N][N][6],tr[N][N][6],jc[]={1,1,2,6},q,n1,n2,nm;
string s[N],rs[N],ans="z";
vector<string>p[N];
void sol(int n1,int n2,int nm,string w)
{
	for(int i=1;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(!(nm&(1<<j)))
				continue;
			if(tr[j][n1][n2]!=-1)
			{
				int z=tr[j][n1][n2],g=(nm^(1<<j));
				if(z!=-1&&dp[nm][j][z])
				{
					w+=(char)(j+'A');
					n1=j;
					n2=z;
					nm=g;
					break;
				}
			}
		}
	}
	if(w<ans)
		ans=w;
}
int main()
{
	ios::sync_with_stdio(0);
	cin>>n>>m;
	r=n-m,q=nm=(1<<n)-1;
	for(int i=0;i<n;i++)
	{
		cin>>s[i];
		rs[i]=s[i];
		reverse(&rs[i][0],&rs[i][m]);
		string t="";
		for(int j=0;j<n;j++)
		{
			int fl=0;
			for(int k=0;k<s[i].size();k++)
			{
				if(s[i][k]=='A'+j)
				{
					fl=1;
					break;
				}
			}
			if(!fl)
				t+=(char)('A'+j);
		}
		do
		{
			p[i].push_back(rs[i]+t);
		}while(next_permutation(&t[0],&t[t.size()]));
	}
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			for(int k=0;k<jc[r];k++)
			{
				string x=p[j][k],t="";
				int y=0;
				for(auto c:x)
				{
					if(c==s[i][y])
						y++;
					else
						t+=c;
				}
				if(y!=m)
					tr[i][j][k]=-1;
				else
				{
					int z=-1;
					t=rs[i]+t;
					for(int l=0;l<jc[r];l++)
						if(p[i][l]==t)
							z=l;
					tr[i][j][k]=z;
				}
			}
		}
	}
	for(int i=0;i<n;i++)
		for(int j=0;j<jc[r];j++)
			dp[1<<i][i][j]=1;
	for(int mask=0;mask<=q;mask++)
	{
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<jc[r];j++)
			{
				if(!dp[mask][i][j])
					continue;
				for(int k=0;k<n;k++)
				{
					if(mask&(1<<k))
						continue;
					for(int l=0;l<jc[r];l++)
						if(tr[i][k][l]==j)
							dp[mask^(1<<k)][k][l]=1;
				}
			}
		}
	}
	for(int j=0;j<n;j++)
	{
		for(int z=0;z<jc[r];z++)
		{
			if(dp[nm][j][z])
			{
				string d="";
				d=d+(char)(j+'A');
				sol(j,z,(nm^(1<<j)),d);
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 27944
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;

// a is subseq of b (b is ordering)
bool is_subseq(const string &a, const string &b){
    int used[256] = {};
    for(char c: a) used[(int)c]++;
    string tmp = "";
    for(char c: b){
        if(used[(int)c] == 1) tmp += c;
    }
    return a == tmp;
}
string remstr(const string &a, const string &b){
    int used[256] = {};
    for(char c: a) used[(int)c]++;
    string res = "";
    for(char c: b){
        if(used[(int)c] == 0) res += c;
    }
    return res;
}

int main(){
    int n,m;
    cin >> n >> m;
    vector<string> str(n);
    for(int i=0; i<n; i++){
        cin >> str[i];
    }
    vector<vector<string>> other(n);
    for(int i=0; i<n; i++){
        bool used[256] = {};
        for(char c: str[i]) used[(int)c] = true;
        string unused = "";
        for(int j=0; j<n; j++){
            if(!used['A'+j]) unused += 'A'+j;
        }
        do{
            other[i].push_back(unused);
        }while(next_permutation(unused.begin(), unused.end()));
    }

    vector<vector<map<string, string>>> dp(1<<n, vector<map<string, string>>(n));
    for(int i=0; i<n; i++){
        for(string &t: other[i]){
            dp[1<<i][i][t] = string(1, 'A'+i);
        }
    }
    for(int i=1; i<(1<<n); i++){
        for(int j=0; j<n; j++){
            for(string &s: other[j]){
                if(dp[i][j].count(s) == 0) continue;
                for(int k=0; k<n; k++){
                    if(i>>k&1) continue;
                    string tmp = s+str[j];
                    reverse(tmp.begin(), tmp.end());
                    if(!is_subseq(str[k], tmp)) continue;
                    int ni = i | (1<<k);
                    string t = remstr(str[k], tmp);
                    reverse(t.begin(), t.end());
                    if(dp[ni][k].count(t) == 0){
                        dp[ni][k][t] = dp[i][j][s] + string(1, 'A'+k);
                    }else{
                        dp[ni][k][t] = min(dp[ni][k][t], dp[i][j][s] + string(1, 'A'+k));
                    }
                }
            }
        }
    }
    string ans = string(n, 'Z');
    for(auto &vm: dp[(1<<n)-1]){
        for(auto &p: vm){
            ans = min(ans, p.second);
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 2200
memory_kb: 153164
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;

// a is subseq of b (b is ordering)
bool is_subseq(const string &a, const string &b){
    int used[256] = {};
    for(char c: a) used[(int)c]++;
    string tmp = "";
    for(char c: b){
        if(used[(int)c] == 1) tmp += c;
    }
    return a == tmp;
}

int main(){
    int n,m;
    cin >> n >> m;
    vector<string> str(n);
    for(int i=0; i<n; i++){
        cin >> str[i];
    }
    vector<vector<string>> other(n);
    for(int i=0; i<n; i++){
        bool used[256] = {};
        for(char c: str[i]) used[(int)c] = true;
        string unused = "";
        for(int j=0; j<n; j++){
            if(!used['A'+j]) unused += 'A'+j;
        }
        do{
            other[i].push_back(unused);
        }while(next_permutation(unused.begin(), unused.end()));
    }

    vector<vector<map<string, string>>> dp(1<<n, vector<map<string, string>>(n));
    for(int i=0; i<n; i++){
        for(string &t: other[i]){
            dp[1<<i][i][t] = string(1, 'A'+i);
        }
    }
    for(int i=1; i<(1<<n); i++){
        for(int j=0; j<n; j++){
            for(string &s: other[j]){
                if(dp[i][j].count(s) == 0) continue;
                for(int k=0; k<n; k++){
                    if(i>>k&1) continue;
                    string tmp = s+str[j];
                    reverse(tmp.begin(), tmp.end());
                    if(!is_subseq(str[k], tmp)) continue;
                    int ni = i | (1<<k);
                    for(string &t: other[k]){
                        if(dp[ni][k].count(t) == 0){
                            dp[ni][k][t] = dp[i][j][s] + string(1, 'A'+k);
                        }else{
                            dp[ni][k][t] = min(dp[ni][k][t], dp[i][j][s] + string(1, 'A'+k));
                        }
                    }
                }
            }
        }
    }
    string ans = string(n, 'Z');
    for(auto &vm: dp[(1<<n)-1]){
        for(auto &p: vm){
            ans = min(ans, p.second);
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 0.30952380952380953
time_ms: 1610
memory_kb: 89496
final_rank: 18

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <functional>
#include <bitset>

template <class T>
std::vector<T> vec(int len, T elem) { return std::vector<T>(len, elem); }

bool contain(const std::string& s, const std::string& t) {
    auto it = t.begin();
    for (char c : s) {
        if (it != t.end() && c == *it) ++it;
    }
    return it == t.end();
}

void solve() {
    int n, k;
    std::cin >> n >> k;

    std::vector<std::pair<std::string, std::string>> ss;
    for (int i = 0; i < n; ++i) {
        std::string s;
        std::cin >> s;

        std::string t;
        for (char c = 'A'; c < 'A' + n; ++c) {
            if (!std::count(s.begin(), s.end(), c)) {
                t.push_back(c);
            }
        }

        do {
            ss.emplace_back(s, t);
        } while (std::next_permutation(t.begin(), t.end()));
    }

    int d = (int)ss.size() / n;

    std::vector<std::vector<int>> to(n * d);
    for (int u = 0; u < n * d; ++u) {
        auto pu = ss[u];

        for (int v = 0; v < n * d; ++v) {
            auto pv = ss[v];

            // uの後に得られる文字列
            auto s = std::string(pu.first.rbegin(), pu.first.rend()) +
                     pu.second;

            if (contain(s, pv.first) &&
                contain(s, pv.second)) {
                to[u].push_back(v);
            }
        }
    }

    auto dp = vec(1 << n, vec(n * d, std::string(1, '$')));
    for (int v = 0; v < n * d; ++v) {
        char c = 'A' + v / d;
        dp.back()[v] = std::string(1, c);
    }

    std::function<std::string(int, int)> dfs =
        [&](int b, int v) -> std::string {
        auto& ret = dp[b][v];
        if (ret != "$") return ret;

        ret = "";
        for (auto u : to[v]) {
            int j = u / d;
            if ((b >> j) & 1) continue;

            auto res = dfs(b | (1 << j), u);
            if (res.empty()) continue;

            if (ret.empty() || res < ret) ret = res;
        }

        if (ret.empty()) return ret;

        char c = 'A' + v / d;
        ret = c + ret;
        return ret;
    };

    std::string ans(n, 'Z');
    for (int v = 0; v < n * d; ++v) {
        int i = v / d;
        auto res = dfs(1 << i, v);

        if (res.empty()) continue;
        ans = std::min(ans, res);
    }

    std::cout << ans << std::endl;
}

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 84428
final_rank: 7

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <functional>

template <class T>
std::vector<T> vec(int len, T elem) { return std::vector<T>(len, elem); }

bool contain(const std::string& s, const std::string& t) {
    auto it = t.begin();
    for (char c : s) {
        if (it != t.end() && c == *it) ++it;
    }
    return it == t.end();
}

void solve() {
    int n, k;
    std::cin >> n >> k;

    std::vector<std::pair<std::string, std::string>> ss;
    for (int i = 0; i < n; ++i) {
        std::string s;
        std::cin >> s;

        std::string t;
        for (char c = 'A'; c < 'A' + n; ++c) {
            if (!std::count(s.begin(), s.end(), c)) {
                t.push_back(c);
            }
        }

        do {
            ss.emplace_back(s, t);
        } while (std::next_permutation(t.begin(), t.end()));
    }

    int d = (int)ss.size() / n;

    std::vector<std::vector<int>> to(n * d);
    for (int u = 0; u < n * d; ++u) {
        auto pu = ss[u];

        for (int v = 0; v < n * d; ++v) {
            auto pv = ss[v];

            // uの後に得られる文字列
            auto s = std::string(pu.first.rbegin(), pu.first.rend()) +
                     pu.second;

            if (contain(s, pv.first) &&
                contain(s, pv.second)) {
                to[u].push_back(v);
            }
        }
    }

    auto dp = vec(1 << n, vec(n * d, std::string(1, '$')));
    for (int v = 0; v < n * d; ++v) {
        char c = 'A' + v / d;
        dp.back()[v] = std::string(1, c);
    }

    std::function<std::string(int, int)> dfs =
        [&](int b, int v) -> std::string {
        auto& ret = dp[b][v];
        if (ret != "$") return ret;

        ret = "";
        for (auto u : to[v]) {
            int j = u / d;
            if ((b >> j) & 1) continue;

            auto res = dfs(b | (1 << j), u);
            if (res.empty()) continue;

            if (ret.empty() || res < ret) ret = res;
        }

        if (ret.empty()) return ret;

        char c = 'A' + v / d;
        return c + ret;
    };

    std::string ans(n, 'Z');
    for (int v = 0; v < n * d; ++v) {
        int i = v / d;
        auto res = dfs(1 << i, v);

        if (res.empty()) continue;
        ans = std::min(ans, res);
    }

    std::cout << ans << std::endl;
}

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 0.07142857142857142
time_ms: 40
memory_kb: 54564
final_rank: 20

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = (1e+18) + 7;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-6;
const ld pi = acos(-1.0);
//typedef vector<vector<ll>> mat;
typedef vector<int> vec;

ll mod_pow(ll a, ll n) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * a%mod;
		a = a * a%mod; n >>= 1;
	}
	return res;
}

struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n%mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint &a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint &a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint &a, modint b) { a.n = ((ll)a.n*b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, int n) {
	if (n == 0)return modint(1);
	modint res = (a*a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p%a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }

//const int max_n = 1 << 22;
//modint fact[max_n], factinv[max_n];
//void init_f() {
//	fact[0] = modint(1);
//	for (int i = 0; i < max_n - 1; i++) {
//		fact[i + 1] = fact[i] * modint(i + 1);
//	}
//	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
//	for (int i = max_n - 2; i >= 0; i--) {
//		factinv[i] = factinv[i + 1] * modint(i + 1);
//	}
//}
//modint comb(int a, int b) {
//	if (a < 0 || b < 0 || a < b)return 0;
//	return fact[a] * factinv[b] * factinv[a - b];
//}

vector<P> to[16][6];

bool used[1 << 16][16][6];
string memo[1 << 16][16][6];
void solve() {
	int n, k; cin >> n >> k;
	vector<string> s(n);
	rep(i, n) {
		cin >> s[i];
	}
	map<string, vector<P>> mp;
	vector<vector<string>> z(n);
	rep(i, n) {
		vector<bool> alf(n, false);
		for (char t : s[i]) {
			alf[t - 'A'] = true;
		}
		string v;
		rep(j, n)if (!alf[j])v.push_back('A' + j);
		string sta = s[i]; reverse(all(sta));
		int tmp = 0;
		while (true) {
			string t = sta + v;
			z[i].push_back(t);
			mp[t].push_back({ i,tmp });
			tmp++;
			if (!next_permutation(all(v)))break;
		}
	}
	rep(i, n) {
		rep(j, z[i].size()) {
			string &ori = z[i][j];
			rep(l, n) {
				if (l == i)continue;
				int tmp = 0;
				rep(x, n) {
					if (tmp < k&&ori[x] == s[l][tmp])tmp++;
				}
				if (tmp == k) {
					string nex;
					tmp = 0;
					rep(x, n) {
						if (tmp < k&&ori[x] == s[l][tmp])tmp++;
						else nex.push_back(ori[x]);
					}
					reverse(all(nex));
					nex += s[l];
					reverse(all(nex));
					//cout << i << " " << l << " " << nex << endl;
					for (P p : mp[nex]) {
						to[i][j].push_back(p);
						//cout << i << " " << j << " add " << p.first << " " << p.second << endl;
					}
				}
			}
		}
	}
	char zz = 'Z' + 1;
	string sup; sup.push_back(zz);
	function<string(int, int, int)> dfs = [&](int s, int i, int j)->string {
		if (s == (1 << n) - 1)return "";
		if (used[s][i][j])return memo[s][i][j];
		used[s][i][j] = true;
		memo[s][i][j] = sup;
		for (P p : to[i][j]) {
			int ni = p.first, nj = p.second;
			if (s&(1 << ni))continue;
			string t = dfs(s ^ (1 << ni), ni, nj);
			if (t != sup)t.insert(t.begin(), 'A' + ni);
			memo[s][i][j] = min(memo[s][i][j], t);
		}
		return memo[s][i][j];
	};
	string ans = sup;
	rep(i, n) {
		rep(j, z[i].size()) {
			string t = dfs(1 << i, i, j);
			if (t != sup)t.insert(t.begin(), 'A' + i);
			ans = min(ans, t);
		}
	}
	cout << ans << endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(12);
	//init_f();
	//int t; cin >> t; rep(i, t)solve();
	solve();
	stop
		return 0;
}
accuracy: 1
time_ms: 430
memory_kb: 60920
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int N = 16;

int lg[ 1 << N ];
bool exi[ N ];
string seq[ N ][ 6 ];
bool ok[ N ][ 6 ][ N ][ 6 ];
bool dp[ 1 << N ][ N ][ 6 ];

int main() {
	ios_base::sync_with_stdio( false );
	cin.tie( nullptr );

	auto two = [] ( int x ) { return 1 << x; };
	auto lowbit = [] ( int x ) { return x & ( -x ); };

	int n, k; cin >> n >> k;
	int jie = ( n - k ) * max( n - k - 1, 1 ) * max( n - k - 2, 1 );

	for ( int i = 0 ; i < n ; ++ i ) {
		string ss; cin >> ss;
		for ( int j = 0 ; j < k ; ++ j )
			exi[ ss[ j ] - 'A' ] = true;
		string per;
		for ( int j = 0 ; j < n ; ++ j )
			if ( not exi[ j ] ) per += char( 'A' + j );
		for ( int j = 0 ; j < n ; ++ j )
			exi[ j ] = false;
		reverse( ss.begin(), ss.end() );
		for ( int j = 0 ; j < jie ; ++ j ) {
			seq[ i ][ j ] = ss + per;
			next_permutation( per.begin(), per.end() );
		}
	}
	for ( int i = 0 ; i < n ; ++ i )
		for ( int j = 0 ; j < jie ; ++ j )
			dp[ two( i ) ][ i ][ j ] = true;

	for ( int i = 0 ; i < n ; ++ i )
		lg[ two( i ) ] = i;

	for ( int i1 = 0 ; i1 < n ; ++ i1 ) {
		for ( int j1 = 0 ; j1 < jie ; ++ j1 ) {
			for ( int i2 = 0 ; i2 < n ; ++ i2 ) {
				for ( int j2 = 0 ; j2 < jie ; ++ j2 ) {
					const string& s1 = seq[ i1 ][ j1 ];
					const string& s2 = seq[ i2 ][ j2 ];

					ok[ i1 ][ j1 ][ i2 ][ j2 ] = true;

					int p1 = k - 1, p2 = k;
					for ( int i = 0 ; i < n ; ++ i ) {
						if ( p1 >= 0 and s1[ i ] == s2[ p1 ] ) {
							-- p1;
						} else if ( p2 < n and s1[ i ] == s2[ p2 ] ) {
							++ p2;
						} else {
							ok[ i1 ][ j1 ][ i2 ][ j2 ] = false;
							break;
						}
					}
				}
			}
		}
	}

	const int S = two( n );
	for ( int s = 3 ; s < S ; ++ s ) {
		vector< int > ps;
		for ( int tmps = s ; tmps ; tmps -= lowbit( tmps ) )
			ps.push_back( lg[ lowbit( tmps ) ] );
		if ( ps.size() == 1 ) continue;
		for ( int u : ps ) {
			for ( int c1 = 0 ; c1 < jie ; ++ c1 ) {
				for ( int v : ps ) {
					if ( u == v ) continue;
					for ( int c2 = 0 ; c2 < jie ; ++ c2 ) {
						if ( ok[ u ][ c1 ][ v ][ c2 ] )
							dp[ s ][ u ][ c1 ] |= dp[ s - two( u ) ][ v ][ c2 ];
						if ( dp[ s ][ u ][ c1 ] ) break;
					}
					if ( dp[ s ][ u ][ c1 ] ) break;
				}
			}
		}
	}

	int state = S - 1;
	string ans;
	while ( state ) {
		for ( int i = 0 ; i < n ; ++ i ) {
			if ( not ( state & two( i ) ) )
				continue;
			for ( int j = 0 ; j < jie ; ++ j ) {
				if ( dp[ state ][ i ][ j ] ) {
					ans += char( 'A' + i );
					state -= two( i );
					break;
				}
			}
			if ( not ( state & two( i ) ) )
				break;
		}
	}
	cout << ans << '\n';
	return 0;
}
accuracy: 0.6190476190476191
time_ms: 260
memory_kb: 9400
final_rank: 16