Language: C++

#include <iostream>
#include <string>
#include <array>
#include <vector>

using namespace std;

array<array<array<unsigned long long,2>,26>,2001> dp;

struct Node {
    vector<Node*> next;
    bool terminal, deadend;

    Node() {
        next.resize(26, NULL);
        terminal = false;
        deadend = true;
    }

    Node* set(int ci, Node *n) {
        next[ci] = n;
        deadend = false;
        return n;
    }
};

bool solve() {
    int N, M;
    unsigned long long K;
    if(!(cin >> N >> M >> K)) return false;

    Node *trie_root = new Node();
    vector<string> words(N);
    for(int i = 0; i < N; ++i) {
        cin >> words[i];
        const int len = words[i].size();
        Node *cur = trie_root;
        for(char c : words[i]) {
            Node *next = cur->next[c-'a'];
            if(next == NULL) {
                next = cur->set(c-'a', new Node());
            }
            cur = next;
        }
        cur->terminal = true;
    }
    vector<unsigned long long> pattern_of(M+1, 0);
    pattern_of[0] = 1;
    for(int i = 0; i <= M; ++i) {
        if(pattern_of[i] > 0) {
            for(const string &word : words) {
                const int ni = i + word.size();
                if(ni > M) continue;
                pattern_of[ni] = min(K+1, pattern_of[ni] + pattern_of[i]);
            }
        }
    }
    if(pattern_of[M] < K) {
        cout << "-" << endl;
        return true;
    }

    for(int i = 0; i <= M; ++i) {
        for(int j = 0; j < 26; ++j) {
            for(int k = 0; k < 2; ++k) {
                dp[i][j][k] = 0;
            }
        }
    }
    string res = "";
    vector<Node*> cur_list;
    cur_list.push_back(trie_root);
    unsigned long long sum = 0;
    for(int i = 0; i < M; ++i) {
        vector<bool> to_see(26, false);
        bool has_root = false;
        for(Node *node : cur_list) {
            for(int ci = 0; ci < 26; ++ci) {
                if(node->next[ci] != NULL) to_see[ci] = true;
            }
            if(node == trie_root) has_root = true;
        }
        if(has_root) {
            for(const string &word : words) {
                int rem_len = M - i - word.size();
                if(rem_len < 0) continue;
                unsigned long long add = pattern_of[rem_len];
                for(int l = 0; l < word.size(); ++l) {
                    const int ci = word[l]-'a';
                    const int end = (l+1 == word.size());
                    dp[i+l][ci][end] += add;
                    if(dp[i+l][ci][end] > K) {
                        dp[i+l][ci][end] = K+1;
                    }
                }
            }
        }
        for(int ci = 0; ci < 26; ++ci) {
            if(!to_see[ci]) continue;
            unsigned long long next = sum + dp[i][ci][0] + dp[i][ci][1];
            //cout << ci << ' ' << next << endl;
            if(next >= K) {
                res += ci+'a';
                bool ended = false;
                for(auto &node : cur_list) {
                    node = node->next[ci];
                    if(node && node->terminal) ended = true;
                }
                auto end = remove_if(cur_list.begin(), cur_list.end(), [](const Node *n) {
                        return n == NULL || n->deadend;
                        });
                cur_list.erase(end, cur_list.end());
                if(ended) {
                    cur_list.push_back(trie_root);
                }
                break;
            }
            sum = next;
        }
    }
    cout << res << endl;
    return true;
}

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

    while(solve()) ;
    return 0;
}

Compiler output:
a.cc: In function 'bool solve()':
a.cc:109:28: error: 'remove_if' was not declared in this scope; did you mean 'remove'?
  109 |                 auto end = remove_if(cur_list.begin(), cur_list.end(), [](const Node *n) {
      |                            ^~~~~~~~~
      |                            remove