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 JavaScript (Node.js 12.16.1) (judge verdict: Accepted)

function Scanner(input) {
	var self = this;
	self.itemNo = 0;
	self.orgStr = input;
	self.splitedStrs = (function(target) {
		var result = [];
		var target = target.replace(/[\n \t]+/g, " ");
		var strs = target.split(" ");
		for (var i = 0, len = strs.length; i < len; i++) {
			result.push(strs[i]);
		}
		return result;
	}(input));

	self.next = function() {
		var result = self.splitedStrs[self.itemNo];
		self.itemNo++;
		return (result != null) ? result : null;
	}

	self.nextInt = function() {
		var result = self.splitedStrs[self.itemNo];
		self.itemNo++;
		return (result != null) ? parseInt(result) : null;
	}

	self.nextBigDecimal = function() {
		var result = self.splitedStrs[self.itemNo];
		self.itemNo++;
		return (result != null) ? parseFloat(result) : null;
	}
	
	self.nextByte = function() {
		var result = self.splitedStrs[self.itemNo];
		self.itemNo++;
		return (result != null) ? new Int8Array(result) : null;
	}

}

// inputに入力データ全体が入る
function Main(sc) {

	var N = sc.nextInt();
	var A = sc.nextInt();
	var B = sc.nextInt();
	var C = sc.nextInt();
	var ABC = { A : A, B : B, C : C, };
	var ans = "Yes";
	var ans2 = [];
	
	var sL = [];
	for (var i = 0; i < N; i++) {
		sL.push(sc.next());
	}
	
	for (var i = 0; i < N; i++) {
		
		var c0 = sL[i].charAt(0);
		var c1 = sL[i].charAt(1);
		var nextS = sL[i + 1];
		
		if (ABC[c0] == 0 && ABC[c1] == 0) {
			ans = "No";
			break;
		}
		
		// 次との共通ターゲット
		var nextShareTs = [];
		var crntNotShareT = "";
		var nextNotShareT = "";
		if (nextS) { 
			if (nextS.indexOf(c0) > -1) {
				nextShareTs.push(c0);
			}
			if (nextS.indexOf(c1) > -1) {
				nextShareTs.push(c1);
			}
			
		}
		
		var plusT = (ABC[c0] < ABC[c1]) ? c0 : c1;
		if (nextShareTs.length == 1 && ABC[c0] == 1 && ABC[c1] == 1) {
			plusT = nextShareTs[0];
		}
		var minusT = (c0 == plusT) ? c1 : c0;
		
		ABC[plusT]++;
		ABC[minusT]--;
		ans2.push(plusT);
	}
	
	// 出力
	console.log((ans == "No") ? ans : ans + "\n" + ans2.join("\n"));
}
Main(new Scanner(require("fs").readFileSync("/dev/stdin", "utf8")));
// Main(new Scanner("33"));

// var str1 = sc.next(); // Stringで取得
// var int1 = sc.nextInt(); // intで取得
// var bd1 = sc.nextBigDecimal(); // BigDecimalで取得
// var byte1 = sc.nextByte(); // byteで取得