{
TASK:gen
LANG:PASCAL
}
program gen;

const
	MAXN					= 100;

type
	TString					= String[100];
	Integer					= LongInt;
	PTree					= ^TTree;
	TTree					= record
		used				: Boolean;
		n				: Array ['A' .. 'Z'] of PTree;
	end;
	PLinkedList				= ^TLinkedList;
	TLinkedList				= record
		c				: Char;
		n				: PLinkedList;
	end;

var
	m					: Array ['A' .. 'Z', 'A' .. 'Z'] of PLinkedList;
	a, b					: Array [1 .. MAXN] of String;
	used					: Array ['A' .. 'Z'] of Boolean;
	t					: Array ['A' .. 'Z'] of PTree;
	cs, s					: String;
	an, bn, i				: Integer;

procedure readInput;
begin
	readln(s);
	readln(an);
	for i := 1 to an do
		readln(a[i]);
	readln(bn);
	for i := 1 to bn do
		readln(b[i]);
end;

procedure build(var p: PTree; s: TString);
var
	ch					: Char;
begin

	if (s = '') then begin
		p^.used := True;
		Exit;
	end;
	if (p^.n[s[1]] = nil) then begin
		new(p^.n[s[1]]);
		p^.n[s[1]]^.used := False;
		for ch := 'A' to 'Z' do p^.n[s[1]]^.n[ch] := nil;
	end;
	build(p^.n[s[1]], copy(s, 2, Length(s)));
end;

procedure mark_used(s: TString);
var
	ch					: Char;
begin
	if (t[s[1]] = nil) then begin
		new(t[s[1]]);
		t[s[1]]^.used := False;
		for ch := 'A' to 'Z' do
			t[s[1]]^.n[ch] := nil;
	end;
	build(t[s[1]], s);

end;

function marked_used(s: TString): Boolean;
var
	fnd					: Boolean;

procedure check_marked(p: PTree; s: TString);
begin
	if (s = '') then begin
		if (p^.used) then fnd := True;
		Exit;
	end;
	if (p^.n[s[1]] <> nil) then
		check_marked(p^.n[s[1]], copy(s, 2, Length(s)));
end;

begin
	if (t[s[1]] = nil) then
		marked_used := False
	else begin
		fnd := False;
		check_marked(t[s[1]], s);
		marked_used := fnd;
	end;
end;

procedure dfs(s: String);
var
	cs					: String;
	p					: PLinkedList;
	i					: Integer;
begin
	mark_used(s);
	if (Length(s) = 1) then begin
		used[s[1]] := True;
		Exit;
	end;
	for i := 1 to Length(s)-1 do begin
		p := m[s[i], s[i+1]];
		while (p <> nil) do begin
			cs := copy(s, 1, i-1) + p^.c + copy(s, i+2, Length(s));
			if (not marked_used(cs)) then
				dfs(cs);
			p := p^.n;
		end;
	end;
end;

procedure go(c: Integer);
var
	i					: Integer;
begin
	if (c = Length(s)+1) then begin
		dfs(cs);
		Exit;
	end;
	for i := 1 to an do
		if (a[i][2] = s[c]) then begin
			cs := cs + a[i][1];
			go(c+1);
			cs := copy(cs, 1, Length(cs)-1);
		end;
end;

procedure add(a, b, c: Char);
var
	p					: PLinkedList;
begin
	if (m[a, b] = nil) then begin
		new(m[a, b]);
		m[a, b]^.n := nil;
		m[a, b]^.c := c;
	end else begin
		p := m[a, b];
		while (p^.n <> nil) do p := p^.n;
		new(p^.n);
		p^.n^.n := nil;
		p^.n^.c := c;
	end;
end;

procedure destroy_list(var p: PLinkedList);
begin
	if (p^.n <> nil) then destroy_list(p^.n);
	dispose(p);
end;

procedure destroy_tree(var p: PTree);
var
	c					: Char;
begin
	for c := 'A' to 'Z' do
		if (p^.n[c] <> nil) then
			destroy_tree(p^.n[c]);
	dispose(p);
end;

procedure Solve;
var
	i, j					: Integer;
	ch					: Char;
	c1, c2					: Char;
	fnd					: Boolean;
begin
	cs := '';
	for c1 := 'A' to 'Z' do
		for c2 := 'A' to 'Z' do
			m[c1, c2] := nil;
	for i := 1 to bn do begin
		add(b[i][2], b[i][3], b[i][1]);
	end;
	for ch := 'A' to 'Z' do begin 
		t[ch] := nil;
		used[ch] := False;
	end;
	go(1);
	fnd := False;
	for ch := 'A' to 'Z' do begin
		if (used[ch]) then fnd := True;
		if (used[ch]) then write(ch);
	end;
	if (not fnd) then writeln(0) else writeln;
	for c1 := 'A' to 'Z' do
		for c2 := 'A' to 'Z' do
			if (m[c1, c2] <> nil) then
				destroy_list(m[c1, c2]);
	for c1 := 'A' to 'Z' do
		if (t[c1] <> nil) then
			destroy_tree(t[c1]);
end;

begin
	readInput;
	Solve;
end.