#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define repeat(i,n) for (long long i = 0; (i) < (n); ++ (i)) #define debug(x) cerr << #x << ": " << x << '\n' #define debugArray(x,n) for(long long i = 0; (i) < (n); ++ (i)) cerr << #x << "[" << i << "]: " << x[i] << '\n' #define debugArrayP(x,n) for(long long i = 0; (i) < (n); ++ (i)) cerr << #x << "[" << i << "]: " << x[i].first<< " " << x[i].second << '\n' using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair Pii; typedef vector vint; typedef vector vll; const ll INF = LLONG_MAX; const ll MOD = 1e9+7; struct UnionFind { vector data; UnionFind(int size) : data(size, -1) { } bool unionSet(int x, int y) { x = root(x); y = root(y); if (x != y) { if (data[y] < data[x]) swap(x, y); data[x] += data[y]; data[y] = x; } return x != y; } bool findSet(int x, int y) { return root(x) == root(y); } int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); } int size(int x) { return -data[root(x)]; } }; typedef ll Weight; struct Edge { int src, dst; Weight weight; Edge(int src, int dst, Weight weight) : src(src), dst(dst), weight(weight) { } }; bool operator < (const Edge &e, const Edge &f) { return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!! e.src != f.src ? e.src < f.src : e.dst < f.dst; } typedef vector Edges; typedef vector Graph; typedef vector Array; typedef vector Matrix; bool visit(const Graph &g, int v, vector &order, vector &color) { color[v] = 1; for(auto e: g[v]) { if (color[e.dst] == 2) continue; if (color[e.dst] == 1) return false; if (!visit(g, e.dst, order, color)) return false; } order.push_back(v); color[v] = 2; return true; } bool topologicalSort(const Graph &g, vector &order) { int n = g.size(); vector color(n); repeat(u, n) if (!color[u] && !visit(g, u, order, color)) return false; reverse(order.begin(),order.end()); return true; } bool used[26]; int main(){ cin.tie(0); ios::sync_with_stdio(false); Graph G(26); UnionFind uf(26); string s; int N;cin>>N; int length=0; repeat(i,N){ cin>>s; length += s.length(); repeat(c,s.length()-1){ used[s[c]-'A']=true; G[s[c]-'A'].push_back({s[c]-'A',s[c+1]-'A',1}); uf.unionSet(s[c]-'A',s[c+1]-'A'); } used[s.back()-'A']=true; } int M;cin>>M; repeat(i,M){ cin>>s; repeat(c,s.length()-1){ G[s[c]-'A'].push_back({s[c]-'A',s[c+1]-'A',1}); uf.unionSet(s[c]-'A',s[c+1]-'A'); } } vint order; topologicalSort(G,order); string ans; repeat(i,26)if(used[order[i]]&&uf.size(order[i])==length){ ans += order[i]+'A'; } if(ans.length()==0){ cout<<-1<