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 Scala (2.13.1) (judge verdict: Runtime Error)

import java.io._
import java.util.StringTokenizer
import scala.util.control.Breaks.{breakable,break}
import scala.collection.mutable.{Map, Stack, Queue, PriorityQueue, Set}

object Main extends App {
  val in = new InputReader(System.in)
  val pw = new PrintWriter(System.out)

  val N = in.next().toInt
  val A, B, C = in.next().toLong
  val s = new Array[String](N+1)
  for (i <- 1 to N) {
    s(i) = in.next()
  }
  val cnt = Array[Long](A, B, C)

  def f(now: String, a: Char): Unit = { // s(i), choice
    val b = now.filter(_ != a)(0)
    a match {
      case 'A' => cnt(0) += 1
      case 'B' => cnt(1) += 1
      case 'C' => cnt(2) += 1
    }
    b match {
      case 'A' => cnt(0) -= 1
      case 'B' => cnt(1) -= 1
      case 'C' => cnt(2) -= 1
    }
  }


  //
  var flag = true
  var ans = new Array[Char](N+1)
  val defo = '0'
  val dp = Array.fill[Char](3)(defo)
  val char = Array[Char]('A','B','C')

  breakable { for (i <- 1 to N) {
    if (cnt.sum == 0) {
      flag = false
    }
    // else if (A + B + C == 2 && (A == 2 ||B==2||C==2)) {




    // }
    else {// if (cnt.sum == 1) {
      val defoNum = dp.count(_ != defo)
      val now = s(i)
      var a = '-'


      now match {
        case "AB" =>
          val (x, y, z) = (0, 1, 2)
          if (dp(x) != '0') {
            a = now.filter(_ != dp(x))(0)
          }
          else if (defoNum == 2) {
            a = now.filter(_ != dp(y)).filter(_ != dp(z))(0)
          }
          else { // 基本ここを書き換えそう
            if (cnt(x) >= 1 && cnt(x) >= cnt(y)) {
              a = now.filter(_ != char(x))(0)
            }
            else if (cnt(y) >= 1 && cnt(y) >= cnt(x)){
              a = now.filter(_ != char(y))(0)
            }
            else {
              flag = false
              break
            }
          }
          dp(x) = a
        case "BC" =>
          val (x, y, z) = (1, 2, 0)
          if (dp(x) != '0') {
            a = now.filter(_ != dp(x))(0)
          }
          else if (defoNum == 2) {
            a = now.filter(_ != dp(y)).filter(_ != dp(z))(0)
          }
          else { // 基本ここを書き換えそう
            if (cnt(x) >= 1 && cnt(x) >= cnt(y)) {
              a = now.filter(_ != char(x))(0)
            }
            else if (cnt(y) >= 1 && cnt(y) >= cnt(x)){
              a = now.filter(_ != char(x))(0)
            }
            else {
              flag = false
              break
            }
          }
          dp(x) = a

        case "AC" =>
          val (x, y, z) = (2, 0, 1)
          if (dp(x) != '0') {
            a = now.filter(_ != dp(x))(0)
          }
          else if (defoNum == 2) {
            a = now.filter(_ != dp(y)).filter(_ != dp(z))(0)
          }
          else { // 基本ここを書き換えそう
            if (cnt(x) >= 1 && cnt(x) >= cnt(y)) {
              a = now.filter(_ != char(x))(0)
            }
            else if (cnt(y) >= 1 && cnt(y) >= cnt(x)){
              a = now.filter(_ != char(x))(0)
            }
            else {
              flag = false
              break
            }
          }
          dp(x) = a
      }

      f(now, a)
      
      ans(i) = a

    }
  }  }

  // output
  if (flag) {
    println("Yes")
    println(ans.drop(1).reverse.mkString("\n"))
  }
  else
    println("No")
}

object Sub {
  def print2DimArray[A](mat: Array[Array[A]]): Unit = {
    mat.foreach(lin => println(lin.toList))
  }
}

class InputReader(stream: InputStream) {
  private[this] val reader = new BufferedReader(new InputStreamReader(stream))
  private[this] var tokenizer: StringTokenizer = new StringTokenizer(reader.readLine())
  def next(): String = {
    while (!tokenizer.hasMoreTokens()) {
      tokenizer = new StringTokenizer(reader.readLine())
    }
    tokenizer.nextToken()
  }
}