package main
import (
"bufio"
"os"
)
type FastScanner struct {
r *bufio.Reader
}
func NewFastScanner() *FastScanner {
return &FastScanner{r: bufio.NewReaderSize(os.Stdin, 1<<20)}
}
func (fs *FastScanner) next() string {
b, err := fs.r.ReadByte()
for err == nil && (b == ' ' || b == '\n' || b == '\r' || b == '\t') {
b, err = fs.r.ReadByte()
}
if err != nil {
return ""
}
buf := make([]byte, 0, 16)
for err == nil && b != ' ' && b != '\n' && b != '\r' && b != '\t' {
buf = append(buf, b)
b, err = fs.r.ReadByte()
}
return string(buf)
}
func parseInt(s string) int {
sign := 1
i := 0
if len(s) > 0 && (s[0] == '-' || s[0] == '+') {
if s[0] == '-' {
sign = -1
}
i++
}
val := 0
for i < len(s) {
val = val*10 + int(s[i]-'0')
i++
}
return sign * val
}
type state struct {
f []int
used []bool
i int
exL bool
exU bool
}
func cloneIntSlice(a []int) []int {
b := make([]int, len(a))
copy(b, a)
return b
}
func cloneBoolSlice(a []bool) []bool {
b := make([]bool, len(a))
copy(b, a)
return b
}
func firstFreeGe(used []bool, from, k int) int {
for y := from; y < k; y++ {
if !used[y] {
return y
}
}
return -1
}
func lastFreeLe(used []bool, to int) int {
for y := to; y >= 0; y-- {
if !used[y] {
return y
}
}
return -1
}
func firstFree(used []bool, k int) int {
for y := 0; y < k; y++ {
if !used[y] {
return y
}
}
return -1
}
func firstFreeInRange(used []bool, l, r int) int {
for y := l; y <= r; y++ {
if !used[y] {
return y
}
}
return -1
}
func solveOne(k int, s, a, b string) (bool, string) {
n := len(s)
sb := []byte(s)
ab := []byte(a)
bb := []byte(b)
f := make([]int, k)
for i := range f {
f[i] = -1
}
used := make([]bool, k)
type Stack = []state
var st Stack
i := 0
exL := true
exU := true
for {
needBT := false
for i < n {
c := int(sb[i] - 'a')
low := int(ab[i] - 'a')
high := int(bb[i] - 'a')
if f[c] != -1 {
y := f[c]
if exL && y < low {
needBT = true
break
}
if exU && y > high {
needBT = true
break
}
if exL && y > low {
exL = false
}
if exU && y < high {
exU = false
}
i++
continue
}
if exL && exU {
if low+1 <= high-1 {
y := firstFreeInRange(used, low+1, high-1)
if y != -1 {
f[c] = y
used[y] = true
exL = false
exU = false
i++
continue
}
}
opts := make([]struct {
y int
nL bool
nU bool
exst bool
}, 0, 2)
if !used[low] {
opts = append(opts, struct {
y int
nL bool
nU bool
exst bool
}{y: low, nL: true, nU: low == high})
}
if high != low && !used[high] {
opts = append(opts, struct {
y int
nL bool
nU bool
exst bool
}{y: high, nL: false, nU: true})
}
if len(opts) == 0 {
needBT = true
break
}
if len(opts) == 2 {
af := cloneIntSlice(f)
au := cloneBoolSlice(used)
af[c] = opts[1].y
au[opts[1].y] = true
st = append(st, state{
f: af,
used: au,
i: i + 1,
exL: opts[1].nL,
exU: opts[1].nU,
})
}
f[c] = opts[0].y
used[opts[0].y] = true
exL = opts[0].nL
exU = opts[0].nU
i++
continue
}
if exL {
y := firstFreeGe(used, low, k)
if y == -1 {
needBT = true
break
}
f[c] = y
used[y] = true
if y > low {
exL = false
}
i++
continue
}
if exU {
y := lastFreeLe(used, high)
if y == -1 {
needBT = true
break
}
f[c] = y
used[y] = true
if y < high {
exU = false
}
i++
continue
}
y := firstFree(used, k)
if y == -1 {
needBT = true
break
}
f[c] = y
used[y] = true
i++
}
if needBT {
if len(st) == 0 {
return false, ""
}
last := st[len(st)-1]
st = st[:len(st)-1]
f = last.f
used = last.used
i = last.i
exL = last.exL
exU = last.exU
continue
}
free := make([]int, 0, k)
for y := 0; y < k; y++ {
if !used[y] {
free = append(free, y)
}
}
ptr := 0
for x := 0; x < k; x++ {
if f[x] == -1 {
f[x] = free[ptr]
ptr++
}
}
out := make([]byte, k)
for x := 0; x < k; x++ {
out[x] = byte('a' + f[x])
}
return true, string(out)
}
}
func main() {
in := NewFastScanner()
out := bufio.NewWriterSize(os.Stdout, 1<<20)
defer out.Flush()
t := parseInt(in.next())
for ; t > 0; t-- {
k := parseInt(in.next())
s := in.next()
a := in.next()
b := in.next()
ok, tmpl := solveOne(k, s, a, b)
if !ok {
out.WriteString("NO\n")
} else {
out.WriteString("YES\n")
out.WriteString(tmpl)
out.WriteByte('\n')
}
}
}