AC自动机+dp。注意最后极值为0的情况,wa一发。
#include<cstdio>
#include<string>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 2005
#define INF 1000000009
typedef long long LL;
int n, m;
char str[105][105];
string path[105][N];
int v[105];
struct Trie {
Trie *fail;
Trie *son[26];
int kind, isword;
}s[N];
Trie *que[N];
int ptr;
int id(char x){
return x - 'a';
}
Trie *NewNode(){
Trie *p = &s[ptr];
for(int i = 0; i < 26; i++)p->son[i] = NULL;
p->fail = NULL;
p->isword = 0;
p->kind = ptr++;
return p;
}
void Insert(char *c, Trie *root, int d){
Trie *tmp = root;
for(int i = 0; c[i]; i++){
if(tmp->son[id(c[i])] == NULL) tmp->son[id(c[i])] = NewNode();
tmp = tmp->son[id(c[i])];
}
tmp->isword += v[d];
}
void Build_fail(Trie *root){
Trie *tmp;
int head = 0, tail = 0;
que[tail++] = root;
root->fail = NULL;
while(head < tail){
tmp = que[head++];
for(int i = 0; i < 26; i++){
if(tmp->son[i]){
if(tmp == root)tmp->son[i]->fail = root;
else {
tmp->son[i]->fail = tmp->fail->son[i];
if(tmp->son[i]->fail->isword)tmp->son[i]->isword += tmp->son[i]->fail->isword;
}
que[tail++] = tmp->son[i];
}
else if(tmp == root)tmp->son[i] = root;
else tmp->son[i] = tmp->fail->son[i];
}
}
}
int dp[105][N];
void solve(){
memset(dp, -1, sizeof(dp));
dp[0][0] = 0;
for(int i = 0; i <= n; i++){
for(int j = 0; j < ptr; j++){
path[i][j].clear();
}
}
for(int i = 1; i <= n; i++){
for(int j = 0; j < ptr; j++){
if(dp[i - 1][j] == -1)continue;
for(int k = 0; k < 26; k++){
Trie *p = &s[j];
if(dp[i][p->son[k]->kind] < dp[i - 1][j] + p->son[k]->isword){
dp[i][p->son[k]->kind] = dp[i - 1][j] + p->son[k]->isword;
path[i][p->son[k]->kind] = path[i - 1][j] + (char)(k + 'a');
}
else if(dp[i][p->son[k]->kind] == dp[i - 1][j] + p->son[k]->isword && path[i - 1][j] + (char)(k + 'a') < path[i][p->son[k]->kind]){
path[i][p->son[k]->kind] = path[i - 1][j] + (char)(k + 'a');
}
}
}
}
int ans = 0;
string str;
for(int i = 0; i <= n; i++){
for(int j = 0; j < ptr; j++){
if(dp[i][j] > ans){
ans = dp[i][j];
}
}
}
if(ans == 0){cout << "" << endl; return ;}
for(int i = 0; i <= n; i++){
for(int j = 0; j < ptr; j++){
if(dp[i][j] == ans && (str == "" || ((str.size() > path[i][j].size()) || (str.size() == path[i][j].size() && str > path[i][j])))){
str = path[i][j];
}
}
}
cout << str << endl;
}
int main(){
int t;
scanf("%d", &t);
while(t--){
ptr = 0;
Trie *root = NewNode();
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++){
scanf("%s", str[i]);
}
for(int i = 0; i < m; i++){
scanf("%d", &v[i]);
}
for(int i = 0; i < m; i++){
Insert(str[i], root, i);
}
Build_fail(root);
solve();
}
return 0;
}