// Solution to Mastermind

import java.util.*;

public class Mastermind {
  public static Scanner in;
  public static int numCases;
  public static int l,c,n; // l = length, c = #colors, n = #guesses made
  public static String alphabet = "ABCDEFGHIJKLMNOPQRST";
  public static char guesses[][]; // past guesses
  public static int b[]; // past responses (black)
  public static int w[]; // past responses (white)
  public static String[] possible; // list of possible solutions left
  public static int bwcount[][]; // scores for possible next guess

  public static void main(String[] args) {
    in = new Scanner(System.in);
    // numCases = in.nextInt();
    numCases = myNextInt();
    for (int i = 0; i < numCases; i++) {
      // l = in.nextInt();
      l = myNextInt();
      bwcount = new int[l+1][l+1];
      // c = in.nextInt();
      c = myNextInt();
      // n = in.nextInt();
      n = myNextInt();
      guesses = new char[n][l];
      b = new int[n];
      w = new int[n];
      for (int j = 0; j < n; j++) {
        // String g = in.nextString();
        String g = myNextString();
        for (int k = 0; k < l; k++) {
          guesses[j][k] = g.charAt(k);
        }
        b[j] = myNextInt();
        w[j] = myNextInt();
      }

//      System.out.println("Case " + (i+1));
      solve();
    }
  }

  // Solve one instance of mastermind. Approach is brute-force:
  // First, determine what solutions are still possible after the
  // guesses have been processed (at most 2000). Then for each of the 
  // (at most 32768) possible next guesses, calculate how
  // many solutions are left in the worst case if that is the next guess.
  public static void solve() {
    String colors = alphabet.substring(0,c);
    // Create a list of all the possible combinations that
    // have not been ruled out by the set of guesses.
    ArrayList<String> possible = new ArrayList<String>();
    String next = "AAAAAAAAAAAAAAAAAAAA".substring(0,l);
    while (!next.equals("")) {
      if (allowed(next,"")) {
        possible.add(next);
      }
      next = getNext(next);
    }
      
    
    // Now try every possible guess to see which one to make:
    next = "AAAAAAAAAAAAAAAAAAAA".substring(0,l);
    String bestSoFar = next;
    int minLeft = possible.size();
    while (!next.equals("")) {
      for (int i = 0; i <= l; i++)
         for (int j = 0; j <= l; j++)
           bwcount[i][j] = 0;
      for (int i = 0; i < possible.size(); i++) {
        String g = possible.get(i);
        allowed(g,next);
      }
      bwcount[l][0] = 0; // DON'T COUNT SOLUTION AS A "REMAINING POSSIBILITY"
      int maxLeft = 0;
      for (int i = 0; i <= l; i++)
        for (int j = 0; j <= l; j++)
          if (bwcount[i][j] > maxLeft)
             maxLeft = bwcount[i][j];
      if (maxLeft < minLeft) {
        minLeft = maxLeft;
        bestSoFar = next;
      }
      next = getNext(next);
    }
    System.out.println(bestSoFar+" "+minLeft);
  }


  // getNext -- return the lexicographically next string after "current"
  public static String getNext(String current) {
    char max = alphabet.charAt(c-1);
    int i = current.length()-1;
    while (i >= 0 && current.charAt(i) == max) i--;
    if (i >= 0)
      return current.substring(0,i)+(char)(1+(int)current.charAt(i))+
              "AAAAAAAAAAAAAAAAAAAA".substring(0,current.length()-i-1);
    else
      return "";
  }

  // allowed -- returns true if and only if the guess "next" is consistent
  // with responses to the guesses already made.
  public static boolean allowed(String next, String guess) {
    if (guess.equals("")) {
    for (int i = 0; i < n; i++) {
      // see if string "next" is compatible with the guesses made so far
      // for each letter in guess and for each letter in next, see if
      // there is a match; this will give us the "black pin" count:
      int black = 0;
      String temp = "";
      String nxttemp = "";
      for (int j = 0; j < l; j++) {
        if (guesses[i][j] == next.charAt(j)) {
            black++;
        }
        else {
            temp = temp+guesses[i][j];
            nxttemp = nxttemp+next.charAt(j);
        }
      }
      if (black != b[i]) return false;
      int white = 0;
      for (int j = 0; j < temp.length(); j++) {
        String c = temp.substring(j,j+1);
        int loc;
        if ((loc = nxttemp.indexOf(c)) >= 0) {
           white++;
           nxttemp = nxttemp.substring(0,loc)+nxttemp.substring(loc+1);
        }
      }
      if (white != w[i]) return false;
    }
    return true;
    }
      int black = 0;
      String temp = "";
      String nxttemp = "";
      for (int j = 0; j < l; j++) {
        if (guess.charAt(j) == next.charAt(j)) {
            black++;
        }
        else {
            temp = temp+guess.charAt(j);
            nxttemp = nxttemp+next.charAt(j);
        }
      }
      int white = 0;
      for (int j = 0; j < temp.length(); j++) {
        String c = temp.substring(j,j+1);
        int loc;
        if ((loc = nxttemp.indexOf(c)) >= 0) {
           white++;
           nxttemp = nxttemp.substring(0,loc)+nxttemp.substring(loc+1);
        }
      }
      bwcount[black][white]++;
    return true;
    
  }

  // Modified "nextInt" to allow me to insert comments in the input file:
  public static int myNextInt() {
    String token = in.next();
    while (token.charAt(0) == '#') {
      in.nextLine();
      token = in.next();
    }
    return Integer.parseInt(token);
  } 

  // Modified "nextString" to allow me to insert comments in the input file:
  public static String myNextString() {
    String token = in.next();
    while (token.charAt(0) == '#') {
      in.nextLine();
      token = in.next();
    }
    return token;
  } 
}
