Problem:
Score : 600 points

Problem Statement

There is a game that involves three variables, denoted A, B, and C.

As the game progresses, there will be N events where you are asked to make a choice.
Each of these choices is represented by a string s_i. If s_i is AB, you must add 1 to A or B then subtract 1 from the other; if s_i is AC, you must add 1 to A or C then subtract 1 from the other; if s_i is BC, you must add 1 to B or C then subtract 1 from the other.

After each choice, none of A, B, and C should be negative.

Determine whether it is possible to make N choices under this condition. If it is possible, also give one such way to make the choices.

Constraints

1 \leq N \leq 10^5

0 \leq A,B,C \leq 10^9

N, A, B, C are integers.

s_i is AB, AC, or BC.

Input

Input is given from Standard Input in the following format:

N A B C
s_1
s_2
:
s_N

Output

If it is possible to make N choices under the condition, print Yes; otherwise, print No.

Also, in the former case, show one such way to make the choices in the subsequent N lines. The (i+1)-th line should contain the name of the variable (A, B, or C) to which you add 1 in the i-th choice.

Sample Input 1

2 1 3 0
AB
AC

Sample Output 1

Yes
A
C

You can successfully make two choices, as follows:

In the first choice, add 1 to A and subtract 1 from B. A becomes 2, and B becomes 2.

In the second choice, add 1 to C and subtract 1 from A. C becomes 1, and A becomes 1.

Sample Input 2

3 1 0 0
AB
BC
AB

Sample Output 2

No

Sample Input 3

1 0 9 0
AC

Sample Output 3

No

Sample Input 4

8 6 9 1
AC
BC
AB
BC
AC
BC
AB
AB

Sample Output 4

Yes
C
B
B
C
C
B
A
A

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	const int D = 6;
	int enc(int a, int b, int c){
		return a * D * D + b * D + c;
	}
	public void Solve(){
		
		A = Math.Min(2, A);
		B = Math.Min(2, B);
		C = Math.Min(2, C);
		

		int[][] dp = new int[N + 1][];
		for(int i=0;i<=N;i++){
			dp[i] = new int[D * D * D];
			for(int j=0;j<D * D * D;j++) dp[i][j] = -1;
		}
		dp[0][enc(A,B,C)] = 0;
		for(int i=0;i<N;i++){
			for(int j=0;j<D * D * D;j++){
				if(dp[i][j] == -1) continue;
				int a = j / (D * D);
				int b = (j / D) % D;
				int c = j % D;
				if(S[i] == "AB"){
					if(a + 1 <= 4 && b - 1 >= 0){
						dp[i + 1][enc(a + 1, b - 1, c)] = j;
					}
					if(a - 1 >= 0 && b + 1 <= 4){
						dp[i + 1][enc(a - 1, b + 1, c)] = j;
					}
					
					
				} else if(S[i] == "AC"){
					if(a + 1 <= 4 && c - 1 >= 0){
						dp[i + 1][enc(a + 1, b, c - 1)] = j;
					}
					if(a - 1 >= 0 && c + 1 <= 4){
						dp[i + 1][enc(a - 1, b, c + 1)] = j;
					}
				} else if(S[i] == "BC"){
					if(b + 1 <= 4 && c - 1 >= 0){
						dp[i + 1][enc(a, b + 1, c - 1)] = j;
					}
					if(b - 1 >= 0 && c + 1 <= 4){
						dp[i + 1][enc(a, b - 1, c + 1)] = j;
					}
				}
			}
		}
		
		int last = -1;
		for(int j=0;j<D * D * D;j++){
			if(dp[N][j] != -1){
				last = j;
				break;
			}
		}
		
		if(last == -1){
			Console.WriteLine("No");
			return;
		}
		
		List<char> L = new List<char>();
		for(int i=N;i>=1;i--){
			int prev = dp[i][last];
			if(prev < 0 || prev >= D * D * D){
				Console.WriteLine("No");
				return;
			}
			int pa = prev / (D * D);
			int pb = (prev / D) % D;
			int pc = prev % D;
			int a = last / (D * D);
			int b = (last / D) % D;
			int c = last % D;
			if(pa < a) L.Add('A');
			else if(pb < b) L.Add('B');
			else if(pc < c) L.Add('C');
			last = prev;
		}
		
		L.Reverse();
		var sb = new StringBuilder();
		sb.AppendLine("Yes");
		foreach(var c in L){
			sb.AppendLine(c.ToString());
		}
		Console.Write(sb.ToString());
		
	}
	int N,A,B,C;
	String[] S;
	public Sol(){
		var d = ria();
		N = d[0]; A = d[1]; B = d[2]; C = d[3];
		S = new String[N];
		for(int i=0;i<N;i++) S[i] = rs();
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}