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 Haskell (GHC 8.8.3) (judge verdict: Accepted)


module Main where

import           Control.Monad
import           Debug.Trace
import qualified Data.Vector                   as V
import qualified Data.Vector.Mutable           as VM
import qualified Data.Vector.Unboxed           as VU
import qualified Data.Vector.Unboxed.Mutable   as VUM
import           Data.List
import qualified Data.ByteString               as BS
import qualified Data.ByteString.Char8         as BSC8
import           Data.Char
import           Data.Maybe
import           Data.Ord
import           Data.Vector.Algorithms.Search
import qualified Data.Array                    as A
import qualified Data.Array.Unboxed            as AU
import qualified Data.Array.IO                 as AIO
import qualified Data.Set                      as S
import qualified Data.Map.Strict               as M

main = do
    [aN, aA, aB, aC] <- getIL
    aS               <- replicateM aN getLine
    let vS = VU.fromList
            $map
            (\x -> if x == "AB" then 1 else if x == "BC" then 2 else 3)
            aS ::VU.Vector Int

    let ret = scanGame (aA,aB,aC) vS
    if ret ==[] 
        then putStrLn "No" 
        else do
                putStrLn "Yes"
                mapM_ (\x->case x of
                    1->putStrLn "A"
                    2->putStrLn "B"
                    3->putStrLn "C")$ reverse ret
               

scanGame :: (Int,Int,Int)->VU.Vector Int-> [Int]
scanGame (a,b,c) s =scanGame' (a,b,c) s []
scanGame' :: (Int,Int,Int)->VU.Vector Int-> [Int]->[Int]
scanGame' (a,b,c) s r
    |a<0||b<0||c<0 = []
    |VU.null s     = r
    |otherwise      = let pro =  VU.head s
                          next = if VU.length s >1 then s VU.! 1 else 0
                          nextPP x =
                                if pro == next then 1 else
                                    case next of
                                        1-> case x of
                                            1->b
                                            2->a
                                            3->1
                                        2-> case x of
                                            1->1
                                            2->c
                                            3->b
                                        3->case x of
                                            1->c
                                            2->1
                                            3->a
                                        _->1
                in case pro of
                            1->if (a>=2) || (a==1 && nextPP 1/=0) 
                                then scanGame' (a-1,b+1,c) (VU.tail s) (2:r) 
                                else scanGame' (a+1,b-1,c) (VU.tail s) (1:r)
                            2->if (b>=2) || (b==1 && nextPP 2/=0) 
                                then scanGame' (a,b-1,c+1) (VU.tail s) (3:r) 
                                else scanGame' (a,b+1,c-1) (VU.tail s) (2:r)
                            3->if (c>=2) || (c==1 && nextPP 3/=0) 
                                then scanGame' (a+1,b,c-1) (VU.tail s) (1:r) 
                                else scanGame' (a-1,b,c+1) (VU.tail s) (3:r)
                            _-> []


fromJustInt :: Maybe Int -> Int
fromJustInt (Just x) = x
fromJustInt Nothing  = 0

getVUI :: IO (VU.Vector Int)
getVUI = VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace) <$> BSC8.getLine
readI :: BSC8.ByteString -> Int
readI = fst . fromJust . BSC8.readInt
readIL :: BSC8.ByteString -> [Int]
readIL = map readI . BSC8.words
readIT2 :: BSC8.ByteString -> (Int, Int)
readIT2 bs =
    let words = BSC8.words bs in (readI $ head words, readI $ last words)
getI :: IO Int
getI = readI <$> BSC8.getLine
getIL :: IO [Int]
getIL = readIL <$> BSC8.getLine
get2IT :: IO (Int, Int)
get2IT = readIT2 <$> BSC8.getLine

getNIS :: Int -> IO [(Int, BSC8.ByteString)]
getNIS 0 = return []
getNIS n = do
    [aFst, aSnd] <- BSC8.words <$> BSC8.getLine
    next         <- (getNIS (n - 1))
    return ((readI aFst, aSnd) : next)

il2ss :: [Int] -> String
il2ss = unwords . map show

il2sn :: [Int] -> String
il2sn = unlines . map show

modNum = 10 ^ 9 + 7
newtype Mint = M Int
instance Num Mint where
    (M a) + (M b) = M $ mod (a + b) modNum
    (M a) - (M b) = M (a - b)
    (M a) * (M b) = M $ mod (a * b) modNum
    fromInteger a = M $ mod (fromInteger a) modNum
    abs (M a) = M $ abs a
    signum (M a) = M $ signum a
instance Show Mint where
    show (M a) = show (mod a modNum)

int2MInt :: Int -> Mint
int2MInt a = M (mod a modNum)

knappsackMaxVal
    :: AIO.IOArray (Int, Int) Int
    -> VU.Vector Int
    -> VU.Vector Int
    -> Int
    -> IO Int
knappsackMaxVal dp volumeVec valueVec dpSize = do
    mapM_
        (\i -> mapM_
            (\v -> do
                let volume = volumeVec VU.! i
                    value  = valueVec VU.! i
                newdp <- if v < volume
                    then AIO.readArray dp (i, v)
                    else do
                        dpIVm <- AIO.readArray dp (i, v - volume)
                        dpIV  <- AIO.readArray dp (i, v)
                        return (max (dpIVm + value) dpIV)
                AIO.writeArray dp (i + 1, v) newdp
            )
            [0 .. dpSize]
        )
        [0 .. VU.length volumeVec - 1]
    AIO.readArray dp (VU.length volumeVec, dpSize)

knappsackMinVol
    :: AIO.IOArray (Int, Int) Int
    -> VU.Vector Int
    -> VU.Vector Int
    -> Int
    -> Int
    -> IO Int
knappsackMinVol dp volumeVec valueVec dpSize maxVolume = do
    mapM_
        (\i -> mapM_
            (\v -> do
                let volume = volumeVec VU.! i
                    value  = valueVec VU.! i
                newdp <- if (v + value) > dpSize
                    then AIO.readArray dp (i, v)
                    else do
                        dpIVm <- AIO.readArray dp (i, v + value)
                        dpIV  <- AIO.readArray dp (i, v)
                        return (min (dpIVm - volume) dpIV)
                AIO.writeArray dp (i + 1, v) newdp
            )
            (reverse [0 .. dpSize])
        )
        [0 .. VU.length valueVec - 1]

    foldM
        (\acc x -> do
            num <- AIO.readArray dp (VU.length volumeVec, x)
            return $ if num <= maxVolume then x else acc
        )
        0
        [0 .. dpSize]