enum Choice { L, R }
impl Choice {
    fn choose(self, l: u8, r: u8) -> u8 { match self { Choice::L => l, Choice::R => r } }
}
fn whatevr() -> Choice { Choice::L }

const A: u8 = b'A';
const B: u8 = b'B';
const C: u8 = b'C';
const AB: (u8, u8) = (A, B);
const BC: (u8, u8) = (B, C);
const AC: (u8, u8) = (A, C);

fn mv(left: &mut usize, right: &mut usize, prefer: Choice) -> Result<Choice, ()> {
    let choice = match (*left, *right) {
        (0, 0) => return Err(()),
        (l, r) if l < r => Choice::L,
        (l, r) if l > r => Choice::R,
        _ => prefer,
    };

    match choice {
        Choice::L => { *left += 1; *right -= 1 },
        Choice::R => { *left -= 1; *right += 1 },
    }

    Ok(choice)
}

fn solve(
    mut a: usize,
    mut b: usize,
    mut c: usize,
    alts: Vec<(u8, u8)>
) -> Result<Vec<u8>, ()> {
    let mut solution = Vec::new();
    let mut alts = alts.into_iter().peekable();
    loop {
        let current = if let Some(alt) = alts.next() {alt} else {break};
        let next = *alts.peek().unwrap_or(&AB);
        let choice = match (current, next) {
            (AB, AB) => mv(&mut a, &mut b, whatevr())?.choose(A, B),
            (AB, BC) => mv(&mut a, &mut b, Choice::R)?.choose(A, B),
            (AB, AC) => mv(&mut a, &mut b, Choice::L)?.choose(A, B),

            (BC, AB) => mv(&mut b, &mut c, Choice::L)?.choose(B, C),
            (BC, BC) => mv(&mut b, &mut c, whatevr())?.choose(B, C),
            (BC, AC) => mv(&mut b, &mut c, Choice::R)?.choose(B, C),

            (AC, AB) => mv(&mut a, &mut c, Choice::L)?.choose(A, C),
            (AC, BC) => mv(&mut a, &mut c, Choice::R)?.choose(A, C),
            (AC, AC) => mv(&mut a, &mut c, whatevr())?.choose(A, C),
            _ => unreachable!(),
        };
        solution.push(choice);
    }
    Ok(solution)
}

fn main() {
    let mut io = IO::new();

    let n = io.read();
    let a = io.read();
    let b = io.read();
    let c = io.read();
    let vs = gen(n, || (io.read_ascii(), io.read_ascii())).collect();

    let ans = solve(a, b, c, vs);
    match ans {
        Err(_) => io.writeln("No"),
        Ok(vs) => {
            io.writeln("Yes");
            io.write_many(vs.iter().map(|&v| v as char));
        }
    }
}


// PROCON LIBRARY //

pub trait Num: Sized {
    fn to_i(self) -> isize;
    fn to_u(self) -> usize { self.to_i() as usize }
    fn off<T: Num>(self, other: T) -> usize { (self.to_i() + other.to_i()).to_u() }
}
impl Num for usize { fn to_i(self) -> isize { self as isize } }
impl Num for isize { fn to_i(self) -> isize { self as isize } }
impl Num for u32 { fn to_i(self) -> isize { self as isize } }
impl Num for i32 { fn to_i(self) -> isize { self as isize } }
impl Num for u64 { fn to_i(self) -> isize { self as isize } }
impl Num for i64 { fn to_i(self) -> isize { self as isize } }

pub struct IdxIterMut<'a, T> {
    iter: std::iter::Enumerate<std::slice::IterMut<'a, T>>,
}

impl<'a, T> Iterator for IdxIterMut<'a, T> {
    type Item=(usize, &'a mut T);
    fn next(&mut self) -> Option<(usize, &'a mut T)> {
        self.iter.next().map(|(i, v)| (i+1, v))
    }
}

pub struct IdxIter<'a, T> {
    iter: std::iter::Enumerate<std::slice::Iter<'a, T>>,
}

impl<'a, T> Iterator for IdxIter<'a, T> {
    type Item=(usize, &'a T);
    fn next(&mut self) -> Option<(usize, &'a T)> {
        self.iter.next().map(|(i, v)| (i+1, v))
    }
}

pub trait SliceExt<T> {
    fn at<I: Num>(&mut self, i: I) -> &mut T;
    fn iter_idx(&self) -> IdxIter<'_, T>;
    fn iter_idx_mut(&mut self) -> IdxIterMut<'_, T>;
}
impl<T> SliceExt<T> for [T] {
    fn at<I: Num>(&mut self, i: I) -> &mut T {
        &mut self[i.to_u() + 1]
    }
    fn iter_idx(&self) -> IdxIter<'_, T> {
        IdxIter {
            iter: self.iter().enumerate(),
        }
    }
    fn iter_idx_mut(&mut self) -> IdxIterMut<'_, T> {
        IdxIterMut {
            iter: self.iter_mut().enumerate(),
        }
    }
}

pub fn gen<T, F: FnMut() -> T>(n: usize, mut f: F) -> impl Iterator<Item=T> {
    (0..n).map(move |_| f())
}

pub struct IO(
    std::io::BufReader<std::io::StdinLock<'static>>,
    std::io::BufWriter<std::io::StdoutLock<'static>>
);
 
impl IO {
    pub fn new() -> IO {
        IO(
            std::io::BufReader::new(Box::leak(Box::new(std::io::stdin())).lock()),
            std::io::BufWriter::new(Box::leak(Box::new(std::io::stdout())).lock())
        )
    }
    pub fn write<D: std::fmt::Display>(&mut self, v: D) {
        use std::io::Write;
        write!(self.1, "{}", v).unwrap();
    }
    pub fn writeln<D: std::fmt::Display>(&mut self, v: D) {
        use std::io::Write;
        writeln!(self.1, "{}", v).unwrap();
    }
    pub fn write_many<D: std::fmt::Display>(&mut self, vs: impl std::iter::IntoIterator<Item=D>) {
        for v in vs {
            self.writeln(v);
        }
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn read_ascii(&mut self) -> u8 {
        use std::io::Read;
        self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .next()
            .expect("Parse error")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
    pub fn pairs<T: std::str::FromStr>(&mut self, n: usize) -> Vec<(T, T)> {
        (0..n).map(|_| (self.read(), self.read())).collect()
    }
}


Measured memory_bytes: 2292