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())
}