// Arup Guha
// 1/23/2015
// Solution to 2013 MCPC Problem G: Cash Cow

// Note: This might be the most annoying floodfill problem ever...

import java.util.*;

public class g {

	final public static int ROWS = 12;
	final public static int COLS = 10;
	final public static char EMPTY = ' ';
	final public static int[] DX = {-1,0,0,1};
	final public static int[] DY = {0,-1,1,0};

	public static int totalFill;

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		int numTurns = stdin.nextInt();
		int loop = 1;

		// Go through each case.
		while (numTurns != 0) {

			// Read in initial grid.
			char[][] grid = new char[ROWS][];
			for (int i=0; i<ROWS; i++)
				grid[i] = stdin.next().toCharArray();

			// Process turns.
			for (int i=0; i<numTurns; i++) {

				// Get row, column and color of the move.
				int c = stdin.next().charAt(0) - 'a';
				int r = ROWS - stdin.nextInt();
				char color = grid[r][c];

				// This is really dumb.
				totalFill = 0;
				boolean[][] used = new boolean[ROWS][COLS];
				fakeFill(grid, r, c, color, used);

				// Fill it, if necessary.
				if (totalFill > 2) floodfill(grid, r, c, color);

				// Drop the pieces.
				drop(grid);

				// This is silly, now move to left...
				left(grid);
			}

			// Output result.
			System.out.println(count(grid));

			// Go to next turn.
			numTurns = stdin.nextInt();
			loop++;
		}
	}

	public static void floodfill(char[][] grid, int r, int c, char color) {

		// Stop!
		if (!inbounds(r,c) || color == EMPTY || grid[r][c] == EMPTY || grid[r][c] != color) return;

		// Fill.
		grid[r][c] = EMPTY;

		// Recurse.
		for (int i=0; i<DX.length; i++)
			floodfill(grid, r+DX[i], c+DY[i], color);
	}

	public static void fakeFill(char[][] grid, int r, int c, char color, boolean[][] used) {

		// Stop!
		if (!inbounds(r,c) || color == EMPTY || used[r][c] || grid[r][c] != color) return;

		// Fake Fill.
		used[r][c] = true;
		totalFill++;

		// Recurse.
		for (int i=0; i<DX.length; i++)
			fakeFill(grid, r+DX[i], c+DY[i], color, used);
	}

	public static void drop(char[][] grid) {

		// Loop through columns.
		for (int j=0; j<COLS; j++) {

			// Get filled rows in this column.
			ArrayList<Integer> filled = new ArrayList<Integer>();
			for (int i=ROWS-1; i>=0; i--)
				if (grid[i][j] != EMPTY)
					filled.add(i);

			// Copy item into row i, col j of grid.
			for (int i=ROWS-1,k=0; i>=ROWS-filled.size(); i--,k++)
				grid[i][j] = grid[filled.get(k)][j];

			// Must empty the rest out =)
			for (int i=ROWS-filled.size()-1; i>=0; i--)
				grid[i][j] = EMPTY;
		}
	}

	public static void left(char[][] grid) {

		// Makes life easier, copy here.
		char[][] tmp = new char[ROWS][COLS];
		for (int i=0; i<ROWS; i++)
			Arrays.fill(tmp[i], EMPTY);

		// Go through each column.
		int cur = 0;
		for (int next=0; next<COLS; next++) {

			// See if this one needs to be copied.
			boolean skip = true;
			for (int i=0; i<ROWS; i++)
				if (grid[i][next] != EMPTY)
					skip = false;

			// Copy if necessary.
			if (!skip) {
				for (int i=0; i<ROWS; i++)
					tmp[i][cur] = grid[i][next];
				cur++;
			}
		}

		// Copy back.
		for (int i=0; i<ROWS; i++)
			for (int j=0; j<COLS; j++)
				grid[i][j] = tmp[i][j];
	}

	// Returns number of cells that aren't empty.
	public static int count(char[][] grid) {

		int cnt = 0;
		for (int i=0; i<ROWS; i++)
			for (int j=0; j<COLS; j++)
				if (grid[i][j] != EMPTY)
					cnt++;
		return cnt;
	}

	public static boolean inbounds(int r, int c) {
		return r >= 0 && r < ROWS && c >= 0 && c < COLS;
	}
}