// Solution to "Translations" by Bob Roos

import java.util.*;
import java.io.*;

// One node in a graph:
class Node {
  public int self;
  public int indeg,outdeg;

  public Node(int i) {
    self = i;
    indeg = outdeg = 0;
  }
}

// An adjacency list representation of the neighbors of a node:
class NodeList {
  public Vector nbr;
  public NodeList() {
    nbr = new Vector();
  }
}

public class Translations {
   static BufferedReader in;
   static StringTokenizer tok;

   static int n; // input: number of phrases in each language
   static int m; // number of nodes in graphs (for graph isomorphism test)
   static int caseNum; // input case number

   static String lang1[][], lang2[][]; // input: lists of 2-word phrases
   static Vector nodes1,nodes2; // alphabetized lists of words in each language

   static NodeList[] g1,g2; // the graphs formed by the 2-word phrases
   static Node[] nl1,nl2; // list of nodes for each graph, including degrees
   static Vector[] cand; // candidates for matching with each node in g1
   static int label[]; // g1 labels for g2 nodes
   static int match[]; // g2 labels for g1 nodes
   static int nummatched; // number of matched nodes

/////////////////////////////////////////////////////////////////////

  // Main: read in the input, set up the problem, and call "iso" to
  // determine the isomorphism:

   public static void main(String[] args) throws IOException {
      caseNum = 0;
      in = new BufferedReader(new InputStreamReader(System.in));
      String line = in.readLine().trim();
      while (line != null) {
        n = Integer.parseInt(line);
        if (n == 0) {
          break;
        }

       // Read in phrases for first language:
        nodes1 = new Vector();
        lang1 = new String[n][2];
        for (int i = 0; i < n; i++) {
          line = in.readLine().trim();
          tok = new StringTokenizer(line);
          lang1[i][0] = tok.nextToken();
          lang1[i][1] = tok.nextToken();

         // add words to the sorted word lists:
          insert(nodes1,lang1[i][0]);
          insert(nodes1,lang1[i][1]);
        }

       // Read in phrases for second language:
        nodes2 = new Vector();
        lang2 = new String[n][2];
        for (int i = 0; i < n; i++) {
          line = in.readLine().trim();
          tok = new StringTokenizer(line);
          lang2[i][0] = tok.nextToken();
          lang2[i][1] = tok.nextToken();

         // add words to the sorted word lists:
          insert(nodes2,lang2[i][0]);
          insert(nodes2,lang2[i][1]);
        }

      // Really a debugging test -- this shouldn't happen!
       if (nodes1.size() != nodes2.size()) {
         System.out.println("impossible");
         continue;
       }

       m = nodes1.size(); // Number of nodes in the two graphs

       // Store as graphs:
        g1 = new NodeList[m];        
        g2 = new NodeList[m];        
        for (int i = 0; i < m; i++) {
          g1[i] = new NodeList();
          g2[i] = new NodeList();
        }

       // Create nodelists for each graph:
        nl1 = new Node[m];
        nl2 = new Node[m];
        for (int i = 0; i < m; i++) {
          nl1[i] = new Node(i);
          nl2[i] = new Node(i);
        }

       // Convert the edge lists into adjacency lists:
        convert(lang1,nodes1,g1,nl1);
        convert(lang2,nodes2,g2,nl2);

/* DEBUG: 
System.out.println("First language:");
for (int i = 0; i < n; i++) 
  System.out.println(lang1[i][0]+"/"+lang1[i][1]);
for (int i = 0; i < g1.length; i++) {
   NodeList nl = (NodeList)g1[i];
   System.out.print(nodes1.get(i)+": indegree = " + nl1[i].indeg+
        ", outdegree = " +nl1[i].outdeg + "\n     ");
   for (int j = 0; j < nl.nbr.size(); j++) {
      Node nd = (Node)nl.nbr.get(j);
      System.out.print(nd.self+" ");
   }
   System.out.println();
}

System.out.println("Second language:");
for (int i = 0; i < n; i++) 
  System.out.println(lang2[i][0]+"/"+lang2[i][1]);
System.out.print("word list: ");
for (int i = 0; i < nodes2.size(); i++)
  System.out.print(nodes2.get(i)+" ");
System.out.println();
for (int i = 0; i < g2.length; i++) {
   NodeList nl = (NodeList)g2[i];
   System.out.print(nodes2.get(i)+": indegree = " + nl2[i].indeg+ 
        ", outdegree = " +nl2[i].outdeg + "\n     ");
   for (int j = 0; j < nl.nbr.size(); j++) {
      Node nd = (Node)nl.nbr.get(j);
      System.out.print(nd.self+" ");
   }
   System.out.println();
}
 END DEBUG */

        caseNum++;
        if (caseNum > 1)
          System.out.println();
        iso();

        line = in.readLine().trim();
      }
   }

/////////////////////////////////////////////////////////////////////

   public static void iso() {
     // First, determine all possible candidate matches based on indegree
     // and outdegree:
     cand = new Vector[m];
     for (int i = 0; i < m; i++) {
//System.out.print("Candidate matches for " + nodes1.get(i));
       cand[i] = new Vector();
       Node first = (Node)nl1[i];
       for (int j = 0; j < m; j++) {
          Node second = nl2[j];
          if (first.indeg == second.indeg && first.outdeg == second.outdeg) {
            cand[i].add(new Integer(j));
//System.out.print(" "+nodes2.get(((Integer)cand[i].get(cand[i].size()-1)).intValue()));
          }
       }
//System.out.println();
     }

     // Initialize matchups:
     label = new int[m];
     match = new int[m];
     for (int i = 0; i < m; i++) {
       label[i] = -1;
       match[i] = -1;
     }

     // Now recursively backtrack search for an isomorphism:
     nummatched = 0;

    // Try all candidates for node 0 (until successful isomorphism):
     for (int k = 0; k < cand[0].size(); k++) {
        int j = ((Integer)cand[0].get(k)).intValue();
        if (recursiveMatch(0,j))
           break;
      }

     for (int i = 0; i < m; i++) {
if (match[i] >= 0) // THIS TEST FOR DEBUGGING ONLY -- ISO SHOULD ALWAYS EXIST
       System.out.println(nodes1.get(i)+"/"+nodes2.get(match[i]));
else
       System.out.println(nodes1.get(i)+"/"+(-1));
     }
   }
/////////////////////////////////////////////////////////////////////

  // Insert unique word into sorted list; these lists will be used
  // for converting words into indices and for determining the output
  // order of the solution.

   public static void insert(Vector nodes, String word) {
     
     for (int i = 0; i < nodes.size(); i++) {
       String temp = (String)nodes.get(i);
       if (word.equals(temp)) // already there -- do nothing
         return;
       if (word.compareTo(temp) < 0) { // found its position -- insert it
         nodes.insertElementAt(word,i);
         return;
       }
     }
     nodes.add(word); // found its position -- insert it
   }

/////////////////////////////////////////////////////////////////////

  // Convert an array of edges, lang, into an array of adjacency lists, g.
  // ("nodes" and "nl" are useful auxiliary arrays for looking up words
  // and maintaining degree information).

   public static void convert(String lang[][], Vector nodes, NodeList[] g,
       Node[] nl) {

     for (int i = 0; i < n; i++) {
       String start = lang[i][0];
       String end = lang[i][1];
       int startpos = nodes.indexOf(start);
       int endpos = nodes.indexOf(end);
       nl[startpos].outdeg++;
       nl[endpos].indeg++;
       g[startpos].nbr.add(nl[endpos]);
     } 
   }

/////////////////////////////////////////////////////////////////////

  public static boolean recursiveMatch(int i, int j) {
    // See if the j has already been matched to something else:
    if (label[j] >= 0 && label[j] != i) {
//System.out.println("Can't match " + nodes1.get(i) +" to "+nodes2.get(j)
//    +"; "+nodes2.get(j)+" is already matched to " + nodes1.get(label[j]));
      return false;
    }

    // It hasn't; see if the matched children of node i agree with
    // the matched children of node j:
    for (int k = 0; k < g1[i].nbr.size(); k++) {
      Node nd = (Node)g1[i].nbr.get(k);
      if (match[nd.self] >= 0) {
         int l = match[nd.self];
         boolean found = false;
//System.out.println("Searching for " + nodes2.get(temp));
         for (int m2 = 0; m2 < g2[j].nbr.size(); m2++) {
            Node nd2 = (Node)g2[j].nbr.get(m2);
            if (l == nd2.self) {
               found = true;
              break;
            }
          }
          if (!found) {
            return false;
          }
      } 
    }

    // See if the matched children of node j agree with
    // the matched children of node i:
    for (int k = 0; k < g2[j].nbr.size(); k++) {
      Node nd = (Node)g2[j].nbr.get(k);
      if (label[nd.self] >= 0) {
         int l = label[nd.self];
         boolean found = false;
//System.out.println("Searching for " + nodes2.get(temp));
         for (int m2 = 0; m2 < g1[i].nbr.size(); m2++) {
            Node nd2 = (Node)g1[i].nbr.get(m2);
            if (l == nd2.self) {
               found = true;
              break;
            }
          }
          if (!found) {
            return false;
          }
      } 
    }

   // Hmm... that's not good enough. So let's also check "back edges".
   // I regret having chosen an adjacency list representation here!
   for (int k = 0; k < m; k++) {
     if (k == i) continue;
     if (match[k] >= 0) {
       // see if i is a child of k; if so, see if j is a child of match[k]:
       for (int l = 0; l < g1[k].nbr.size(); l++) {
         Node nd = (Node)g1[k].nbr.get(l);
         if (nd.self == i) {
           boolean found = false;
           for (int m2 = 0; m2 < g2[match[k]].nbr.size(); m2++) {
             Node nd2 = (Node)g2[match[k]].nbr.get(m2);
             if (nd2.self == j) {
                found = true;
                break;
             }
           }
           if (!found)
             return false;
         }
       }
     }
   }

   // They agree; do the matchup:
    label[j] = i;
    match[i] = j;
    nummatched++;
//System.out.println("Trying to match " + nodes1.get(i)+" to " + nodes2.get(j));

    // If this is the last node to be matched, verify the graph isomorphism:
    if (nummatched == m) {
//System.out.println("Testing iso:");
      boolean invalid = false;
      for (int k = 0; k < m; k++) {
         int l = match[k];
//System.out.println("Comparing "+nodes1.get(k)+" and "+nodes2.get(l));
         // see if neighborlist of k in g1 matches neighbor list of l in g2:
         for (int m3 = 0; m3 < g1[k].nbr.size(); m3++) {
            Node nd = (Node)g1[k].nbr.get(m3);
            int ndname = nd.self;
//System.out.println("Child " + nodes1.get(ndname));
            boolean found = false;
            int temp = match[ndname];
//System.out.println("Searching for " + nodes2.get(temp));
            for (int m2 = 0; m2 < g2[l].nbr.size(); m2++) {
               Node nd2 = (Node)g2[l].nbr.get(m2);
               if (temp == nd2.self) {
                  found = true;
                 break;
               }
             }
             if (!found) {
               invalid = true;
               break;
             }
          }
          if (invalid) break;
      }
      if (invalid) {         
         label[j] = -1;
         match[i] = -1;
         nummatched--;
         return false;
      }
      return true;
  }

  // Match one more node:
    for (int k = 0; k < cand[i+1].size(); k++) {
      int m = ((Integer)cand[i+1].get(k)).intValue();
      if (recursiveMatch(i+1,m))
         return true;
     }
     label[j] = -1;
     match[i] = -1;
     nummatched--;
     return false;
   }
  
/////////////////////////////////////////////////////////////////////

/*
  // Insert Node into sorted list.

   public static void insertNode(Vector nodes, Node nd, int id) {
     
     for (int i = 0; i < nodes.size(); i++) {
       Node temp = (Node)nodes.get(i);
       if (id == temp.self) // already there -- do nothing
         return;
       if (id < temp.self) { // found its position -- insert it
         nodes.insertElementAt(nd,i);
         return;
       }
     }
     nodes.add(word); // found its position -- insert it
   }
*/
}
