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 Rust (1.42.0) (judge verdict: Accepted)

#![allow(unused_imports)]
#![allow(clippy::many_single_char_names)]
#![allow(clippy::suspicious_arithmetic_impl)]

// using Rust(1.42.0)
// My Library Repo is at "https://github.com/Loptall/prcn_lib"
// check available crates on AtCoder at "https://atcoder.jp/contests/language-test-202001"

/*
    AtCoder Language Update 2020204 お疲れ様でした! 有難いです
*/

// Dep crates are...
use std::cmp::{max, min, Ordering};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
use std::mem::swap;
use std::ops::*;
use std::{i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize};

use itertools::*;
use itertools_num::*;
use lazy_static::lazy_static;
use maplit::{btreemap, btreeset, hashmap, hashset};
use num_bigint::{BigInt, BigUint};
use num_integer::{binomial, gcd, lcm, Integer};
use permutohedron::Heap;
use proconio::{fastout, input, is_stdin_empty, marker::*};
use rand::random;

// code...
fn main() {
    input! {
        n: usize, mut a: usize, mut b: usize, mut c: usize,
        s: [String; n]
    }

    let mut ans = "Yes";
    let mut chose = Vec::with_capacity(n);
    let mut abc = vec![a, b, c];

    for (now, next) in s.iter().tuple_windows() {
        let cln = abc.clone();
        let (first, second) = to_abc(&mut abc, now);
        if *first + *second == 0 {
            ans = "No";
            break;
        } else if *first + *second == 1 {
            if *first == 1 {
                chose.push(now.chars().nth(1).unwrap());
            } else {
                chose.push(now.chars().nth(0).unwrap());
            }
            swap(first, second);
        } else {
            if *first == 0 {
                *first += 1;
                *second -= 1;
                chose.push(now.chars().nth(0).unwrap());
            } else if *second == 0 {
                *first -= 1;
                *second += 1;
                chose.push(now.chars().nth(1).unwrap());
            } else {
                match common_abc(&now, &next, &cln) {
                    Some('A') => {
                        *first += 1;
                        *second -= 1;
                        chose.push('A');
                    }
                    Some('B') => {
                        chose.push('B');
                        if &now[..] == "AB" {
                            *first -= 1;
                            *second += 1;
                        } else {
                            *first += 1;
                            *second -= 1;
                        }
                    }
                    Some('C') => {
                        *first -= 1;
                        *second += 1;
                        chose.push('C');
                    }
                    Some(_) => unreachable!(),
                    None => {
                        ans = "No";
                        break;
                    }
                }
            }
        }
    }

    let last: (usize, usize) = s
        .last()
        .unwrap()
        .chars()
        .collect_vec()
        .into_iter()
        .map(|x: char| match x {
            'A' => 0,
            'B' => 1,
            'C' => 2,
            _ => unreachable!(),
        })
        .collect_tuple()
        .unwrap();

    if abc[last.0] == 0 && abc[last.1] == 0 {
        ans = "No";
    } else {
        chose.push(
            match if abc[last.0] < abc[last.1] {
                last.0
            } else {
                last.1
            } {
                0 => 'A',
                1 => 'B',
                2 => 'C',
                _ => unreachable!(),
            },
        )
    }

    println!("{}", ans);
    if ans == "Yes" {
        println!("{}", chose.iter().join("\n"));
    }
}

fn to_abc<'a>(abc: &'a mut [usize], now: &String) -> (&'a mut usize, &'a mut usize) {
    let ptr = abc.as_mut_ptr();
    match &now[..] {
        "AB" => unsafe { (&mut *ptr, &mut *ptr.add(1)) },
        "BC" => unsafe { (&mut *ptr.add(1), &mut *ptr.add(2)) },
        "AC" => unsafe { (&mut *ptr, &mut *ptr.add(2)) },
        _ => unreachable!(),
    }
}

fn common_abc(now: &String, next: &String, abc: &Vec<usize>) -> Option<char> {
    match (&now[..], &next[..]) {
        ("AB", "BC") | ("BC", "AB") => Some('B'),
        ("BC", "AC") | ("AC", "BC") => Some('C'),
        ("AC", "AB") | ("AB", "AC") => Some('A'),
        (s, t) if s == t => Some({
            match s {
                "AB" => {
                    if abc[0] >= abc[1] {
                        'A'
                    } else {
                        'B'
                    }
                }
                "BC" => {
                    if abc[1] >= abc[2] {
                        'B'
                    } else {
                        'C'
                    }
                }
                "AC" => {
                    if abc[0] >= abc[2] {
                        'A'
                    } else {
                        'C'
                    }
                }
                _ => unreachable!(),
            }
        }),
        _ => None,
    }
}