← Home
package main

import (
	"bytes"
	"io"
	"os"
)

type Scanner struct {
	data []byte
	idx  int
	n    int
}

func NewScanner() *Scanner {
	b, _ := io.ReadAll(os.Stdin)
	return &Scanner{data: b, n: len(b)}
}

func (s *Scanner) skip() {
	for s.idx < s.n {
		c := s.data[s.idx]
		if c > ' ' {
			break
		}
		s.idx++
	}
}

func (s *Scanner) NextInt() int {
	s.skip()
	sign := 1
	if s.data[s.idx] == '-' {
		sign = -1
		s.idx++
	}
	x := 0
	for s.idx < s.n {
		c := s.data[s.idx]
		if c < '0' || c > '9' {
			break
		}
		x = x*10 + int(c-'0')
		s.idx++
	}
	return x * sign
}

func (s *Scanner) NextString() string {
	s.skip()
	start := s.idx
	for s.idx < s.n && s.data[s.idx] > ' ' {
		s.idx++
	}
	return string(s.data[start:s.idx])
}

type Set struct {
	cnt uint8
	_   [3]byte
	l   [8]int32
	r   [8]int32
}

func single(v int32) Set {
	var s Set
	s.cnt = 1
	s.l[0] = v
	s.r[0] = v
	return s
}

func contains(s Set, x int32) bool {
	for i := 0; i < int(s.cnt); i++ {
		if s.l[i] <= x && x <= s.r[i] {
			return true
		}
	}
	return false
}

func shiftSet(s Set, d int32) Set {
	if d == 0 {
		return s
	}
	for i := 0; i < int(s.cnt); i++ {
		s.l[i] += d
		s.r[i] += d
	}
	return s
}

func unionSets(a, b Set) Set {
	var tl [16]int32
	var tr [16]int32
	m := 0
	for i := 0; i < int(a.cnt); i++ {
		tl[m] = a.l[i]
		tr[m] = a.r[i]
		m++
	}
	for i := 0; i < int(b.cnt); i++ {
		tl[m] = b.l[i]
		tr[m] = b.r[i]
		m++
	}
	for i := 0; i < m; i++ {
		for j := i + 1; j < m; j++ {
			if tl[j] < tl[i] || (tl[j] == tl[i] && tr[j] < tr[i]) {
				tl[i], tl[j] = tl[j], tl[i]
				tr[i], tr[j] = tr[j], tr[i]
			}
		}
	}
	var rl [16]int32
	var rr [16]int32
	rc := 0
	for i := 0; i < m; i++ {
		if rc == 0 || tl[i] > rr[rc-1]+1 {
			rl[rc] = tl[i]
			rr[rc] = tr[i]
			rc++
		} else if tr[i] > rr[rc-1] {
			rr[rc-1] = tr[i]
		}
	}
	var res Set
	if rc > 8 {
		rc = 8
	}
	res.cnt = uint8(rc)
	for i := 0; i < rc; i++ {
		res.l[i] = rl[i]
		res.r[i] = rr[i]
	}
	return res
}

func main() {
	in := NewScanner()
	t := in.NextInt()
	var out bytes.Buffer
	for ; t > 0; t-- {
		n := in.NextInt()
		k := in.NextInt()
		str := in.NextString()
		s := make([]byte, n)
		for i := 0; i < n; i++ {
			if str[i] == 'B' {
				s[i] = 1
			}
		}

		topDiff := 0
		for i := 1; i < n; i++ {
			if s[i] != s[i-1] {
				topDiff++
			}
		}

		target := k - topDiff
		if target < 0 {
			out.WriteString("NO\n")
			continue
		}

		dp0 := make([]Set, n)
		dp1 := make([]Set, n)

		if s[0] == 0 {
			dp0[0] = single(0)
			dp1[0] = single(1)
		} else {
			dp0[0] = single(1)
			dp1[0] = single(0)
		}

		for i := 1; i < n; i++ {
			var c0, c1 int32
			if s[i] != 0 {
				c0 = 1
			}
			if s[i] != 1 {
				c1 = 1
			}
			dp0[i] = unionSets(shiftSet(dp0[i-1], c0), shiftSet(dp1[i-1], c0+1))
			dp1[i] = unionSets(shiftSet(dp1[i-1], c1), shiftSet(dp0[i-1], c1+1))
		}

		m := int32(target)
		end := byte(2)
		if contains(dp0[n-1], m) {
			end = 0
		} else if contains(dp1[n-1], m) {
			end = 1
		}

		if end == 2 {
			out.WriteString("NO\n")
			continue
		}

		ans := make([]byte, n)
		curChar := end
		curScore := m
		ans[n-1] = byte('A' + curChar)

		for i := n - 1; i >= 1; i-- {
			var vert int32
			if curChar != s[i] {
				vert = 1
			}

			var sameSet Set
			if curChar == 0 {
				sameSet = dp0[i-1]
			} else {
				sameSet = dp1[i-1]
			}

			if curScore >= vert && contains(sameSet, curScore-vert) {
				ans[i-1] = byte('A' + curChar)
				curScore -= vert
				continue
			}

			prevChar := curChar ^ 1
			var prevSet Set
			if prevChar == 0 {
				prevSet = dp0[i-1]
			} else {
				prevSet = dp1[i-1]
			}
			if curScore >= vert+1 && contains(prevSet, curScore-vert-1) {
				ans[i-1] = byte('A' + prevChar)
				curScore -= vert + 1
				curChar = prevChar
				continue
			}
			ans[i-1] = byte('A' + prevChar)
			curScore -= vert + 1
			curChar = prevChar
		}

		out.WriteString("YES\n")
		out.Write(ans)
		out.WriteByte('\n')
	}
	os.Stdout.Write(out.Bytes())
}