/*
 * TODOEJ: write actual solution.
 *
 * First idea:
 * Sort the letters of each word and make a trie of the resulting words. Keep track which words correspond to a certain sorted word.
 * Sort the letters of the query. Set two word pointers at the root. Now follow the letters of the sorted query. At each step you
 * have maximal two possibilities (take the letter in the first pointer or in the second pointer). Take care that you don't take
 * for example E in first, E in second and then E in first again, since this will overcount. When all the letters are processed,
 * check each wordpart if they match the letters which were in the right position. Now add the product of the number of valid words
 * for the first part and the number of valid words for the second wordpart to the result.
 * Complexity: O(2^10+10*n+m) per query, where m is the number of words matching the query, but far less in allmost all cases.
 */
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

#define PB push_back
#define SZ(v) ((int)(v).size())
#define MP make_pair
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define REPSZ(i,v) REP(i,SZ(v))


typedef struct Node {
	vector<int> words;
	Node* next[26];
	int depth;
} Node;

int n,nq;
char words[1000][10];
char sortedwords[1000][10];
char query[11];
char sortedquery[11];

int nrnodes;
Node nodes[1+9*1000];
Node* root;
Node* createnode(int depth) {
	nodes[nrnodes].words.clear();
	memset(nodes[nrnodes].next,0,sizeof(nodes[nrnodes].next));
	nodes[nrnodes].depth=depth;
	return &nodes[nrnodes++];
}

vector<string> ret;
void go(int pos,Node *a,Node *b,int noa) {
	if(sortedquery[pos]=='\0') {
		vector<int> A,B;
		REPSZ(x,a->words) {
			int i=a->words[x];
			bool ok=true;
			REP(j,a->depth) if(islower(query[j])&&query[j]!=words[i][j]) { ok=false; break; }
			if(ok) A.PB(i);
		}
		REPSZ(x,b->words) {
			int i=b->words[x];
			bool ok=true;
			REP(j,b->depth) if(islower(query[a->depth+j])&&query[a->depth+j]!=words[i][j]) { ok=false; break; }
			if(ok) B.PB(i);
		}
		REPSZ(i,A) REPSZ(j,B) ret.PB(string(words[A[i]])+"-"+words[B[j]]);
	} else {
		int k=sortedquery[pos]-'a';
		if(k!=noa&&a->next[k]!=NULL) go(pos+1,a->next[k],b,noa);
		if(b->next[k]!=NULL) go(pos+1,a,b->next[k],k);
	}
}

void run() {
	scanf("%d",&n);
	REP(i,n) scanf("%s",words[i]);
	
	nrnodes=0;
	root=createnode(0);
	REP(i,n) {
		strcpy(sortedwords[i],words[i]);
		sort(sortedwords[i],sortedwords[i]+strlen(sortedwords[i]));
		Node* cur=root;
		for(int j=0;sortedwords[i][j]!='\0';++j) {
			int k=sortedwords[i][j]-'a';
			if(cur->next[k]==NULL) cur->next[k]=createnode(cur->depth+1);
			cur=cur->next[k];
		}
		cur->words.PB(i);
	}
	
	scanf("%d",&nq);
	REP(q,nq) {
		scanf("%s",query);
		strcpy(sortedquery,query);
		for(int j=0;sortedquery[j]!='\0';++j) sortedquery[j]=tolower(sortedquery[j]);
		sort(sortedquery,sortedquery+strlen(sortedquery));
		ret.clear();
		go(0,root,root,-1);
		sort(ret.begin(),ret.end());
		printf("%d\n",SZ(ret));
		REPSZ(i,ret) { if( i == 1000 ) break; printf("%s\n",ret[i].c_str()); }
	}
}

int main() {
	int n; scanf("%d",&n); FORE(i,1,n) run();
	return 0;
}
