You are given an integer $k$ and a string $s$ that consists only of characters 'a' (a lowercase Latin letter) and '*' (an asterisk).

Each asterisk should be replaced with several (from $0$ to $k$ inclusive) lowercase Latin letters 'b'. Different asterisk can be replaced with different counts of letter 'b'.

The result of the replacement is called a BA-string.

Two strings $a$ and $b$ are different if they either have different lengths or there exists such a position $i$ that $a_i \neq b_i$.

A string $a$ is lexicographically smaller than a string $b$ if and only if one of the following holds:

$a$ is a prefix of $b$, but $a \ne b$;

in the first position where $a$ and $b$ differ, the string $a$ has a letter that appears earlier in the alphabet than the corresponding letter in $b$.

Now consider all different BA-strings and find the $x$-th lexicographically smallest of them.


-----Input-----

The first line contains a single integer $t$ ($1 \le t \le 2000$) — the number of testcases.

The first line of each testcase contains three integers $n$, $k$ and $x$ ($1 \le n \le 2000$; $0 \le k \le 2000$; $1 \le x \le 10^{18}$). $n$ is the length of string $s$.

The second line of each testcase is a string $s$. It consists of $n$ characters, each of them is either 'a' (a lowercase Latin letter) or '*' (an asterisk).

The sum of $n$ over all testcases doesn't exceed $2000$. For each testcase $x$ doesn't exceed the total number of different BA-strings. String $s$ contains at least one character 'a'.


-----Output-----

For each testcase, print a single string, consisting only of characters 'b' and 'a' (lowercase Latin letters) — the $x$-th lexicographically smallest BA-string.


-----Examples-----

Input
3
2 4 3
a*
4 1 3
a**a
6 3 20
**a***
Output
abb
abba
babbbbbbbbb


-----Note-----

In the first testcase of the example, BA-strings ordered lexicographically are:

a

ab

abb

abbb

abbbb

In the second testcase of the example, BA-strings ordered lexicographically are:

aa

aba

abba

Note that string "aba" is only counted once, even though there are two ways to replace asterisks with characters 'b' to get it.

Difficulty: MEDIUM_HARD
Tags: Implementation

Greedy algorithms

Complete search

Dynamic programming

Mathematics
Skill types: Dynamic programming

Complete search

Greedy algorithms

Starter code:

Solutions:
sr = lambda : input()
ir = lambda : int(sr())
lr = lambda : list(map(int, sr().split()))
inf = 10 ** 18
mod = 998244353
test = ir()
for t in range(test):
	(n, k, x) = lr()
	a = sr()
	count = []
	pre = ''
	now = 0
	start_inds = []
	for c in a:
		if c == '*':
			if pre == '*':
				now += 1
			else:
				now = 1
		else:
			if now > 0:
				count.append(now * k + 1)
			now = 0
		pre = c
	if now > 0 and pre == '*':
		count.append(now * k + 1)
	count.reverse()
	count_per = [1]
	x -= 1
	start = 0
	for (ind, num) in enumerate(count[:-1]):
		count_per.append(num * count_per[-1])
		if count_per[-1] > 10 ** 18:
			start = len(count) - 1 - ind
			count_per.pop()
			break
	for i in range(start):
		count.pop()
	count.reverse()
	count_per.reverse()
	nums = []
	ret = x
	for num in count_per:
		tmp = ret // num
		nums.append(tmp)
		ret = ret % num
	ans = []
	now_count = 0
	now = 0
	for c in a:
		if c == '*':
			if pre == '*':
				now += 1
			else:
				now = 1
		else:
			if now > 0:
				if now_count >= start:
					ind = now_count - start
					for _ in range(nums[ind]):
						ans.append('b')
				now_count += 1
			ans.append('a')
			now = 0
		pre = c
	if pre == '*':
		if now_count >= start:
			ind = now_count - start
			for _ in range(nums[ind]):
				ans.append('b')
		now_count += 1
	print(*ans, sep='')


t = int(input())
for i in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	arr = []
	cnt = 0
	for i in range(n):
		if s[i] == '*':
			cnt += 1
		elif cnt > 0:
			arr.append(cnt * k)
			cnt = 0
	if cnt > 0:
		arr.append(cnt * k)
	l = len(arr)
	res = [0 for i in range(l)]
	ind = 0
	if 'a' in s:
		for i in range(l):
			arr[i] += 1
		r = [0 for i in range(l)]
		for i in range(l - 1, -1, -1):
			if i == l - 1:
				r[i] = arr[i]
			else:
				r[i] = arr[i] * r[i + 1]
			if r[i] >= x:
				ind = i
				break
		for i in range(ind, l):
			if i < l - 1:
				if x % r[i + 1] == 0:
					df = x // r[i + 1] - 1
				else:
					df = x // r[i + 1]
				res[i] = df
				x -= df * r[i + 1]
			else:
				res[i] = x - 1
		cnt = 0
		st = ''
		ind = 0
		for i in range(n):
			if s[i] == '*':
				cnt += 1
			else:
				if cnt > 0:
					st += 'b' * res[ind]
					ind += 1
					cnt = 0
				st += s[i]
		if cnt > 0:
			st += 'b' * res[ind]
		print(st)
	else:
		st = 'b' * x
		print(st)


import sys
import os.path
from collections import *
import math
import bisect
import heapq as hq
from fractions import Fraction
from random import randint
if os.path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')
input = sys.stdin.readline

def solve():
	(n, k, x) = [int(x) for x in input().split()]
	s = list(input().strip('\n'))
	y = 0
	h = Counter(s)
	if h['*'] == 0:
		print(''.join(s))
		return
	if k == 0:
		for i in range(len(s)):
			if s[i] == '*':
				s[i] = ''
		print(''.join(s))
		return
	s.append('b')
	cnt = 0
	arr = []
	for i in range(len(s)):
		if s[i] == '*':
			cnt += k
		else:
			if cnt:
				arr.append(cnt)
			cnt = 0
	s.pop()
	prod = 1
	for i in range(len(arr)):
		prod *= arr[i] + 1
	x = min(x, prod)
	x -= 1
	arr = arr[::-1]
	for i in range(len(arr)):
		arr[i] += 1
		if x == 0:
			arr[i] = 0
			continue
		temp = x % arr[i]
		x //= arr[i]
		arr[i] = temp
	arr = arr[::-1]
	s1 = []
	for i in range(n):
		if s[i] == '*' and (i == 0 or s[i - 1] != '*'):
			s1.append(s[i])
		elif s[i] != '*':
			s1.append(s[i])
	k = 0
	for i in range(len(s1)):
		if s1[i] == '*':
			s1[i] = arr[k] * 'b'
			k += 1
	print(''.join(s1))
t = int(input())
while t:
	t -= 1
	solve()


import sys
from typing import Deque

def input():
	return sys.stdin.readline().rstrip()
DXY = [(0, -1), (1, 0), (0, 1), (-1, 0)]
mod = 998244353
inf = 1 << 64

def ceil(x, y):
	return (x + y - 1) // y
from collections import deque

def slv():
	(n, k, X) = map(int, input().split())
	S = input()
	cnt = 0
	a = deque([])
	for i in range(n):
		if S[i] != '*':
			if cnt > 0:
				a.append(k * cnt + 1)
			cnt = 0
		else:
			cnt += 1
		if i == n - 1 and cnt > 0:
			a.append(k * cnt + 1)
	total = 1
	b = deque([])
	while total <= X and a:
		v = a.pop()
		b.appendleft(v)
		total *= v
	a = deque([1] * len(a))
	c = deque([])
	for e in b:
		total //= e
		ord = ceil(X, total)
		c.append(ord)
		X -= (ord - 1) * total
	while c:
		a.append(c.popleft())
	string = []
	(cnt, itr) = (0, 0)
	for i in range(len(S)):
		if S[i] == 'a':
			string.append('a')
		elif i + 1 == len(S) or S[i + 1] == 'a':
			string.append('b' * (a[itr] - 1))
			itr += 1
	print(''.join(string))
	return

def main():
	t = int(input())
	for i in range(t):
		slv()
	return 0
main()


t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	s = input()[::-1]
	x = x - 1
	res = []
	i = 0
	while i < n:
		if s[i] == 'a':
			res.append(s[i])
		else:
			j = i
			while j + 1 < n and s[j + 1] == s[j]:
				j += 1
			d = (j - i + 1) * k + 1
			res.append('b' * (x % d))
			x //= d
			i = j
		i += 1
	print(''.join(res)[::-1])


for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	x -= 1
	s = input()
	L = []
	if s[0] == 'a':
		M = []
	else:
		M = [0]
	t = 0
	a = 0
	for i in range(n):
		if s[i] == '*':
			t += 1
			if a != 0:
				M.append(a)
				a = 0
		else:
			a += 1
			if t != 0:
				L.append(t * k + 1)
				t = 0
	if t != 0:
		L.append(t * k + 1)
	else:
		M.append(a)
	N = [0] * len(L)
	for j in range(-1, -len(L) - 1, -1):
		N[j] = x % L[j]
		x = x // L[j]
	for i in range(len(N)):
		print('a' * M[i], 'b' * N[i], sep='', end='')
	if len(M) > len(L):
		print('a' * M[-1])
	else:
		print()


import sys
import math
input = sys.stdin.readline
mod = 998244353

def power(num, ex):
	(pw, res) = (num, 1)
	while ex:
		if ex & 1:
			res = res * pw
		pw = pw * pw
		ex >>= 1
	return res

def power_with_modulo(num, ex):
	(pw, res) = (num % mod, 1)
	while ex:
		if ex & 1:
			res = res * pw % mod
		pw = pw * pw % mod
		ex >>= 1
	return res
t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	s = str(input())
	ans = ''
	i = n - 1
	x -= 1
	while i >= 0:
		if s[i] == 'a':
			ans += 'a'
			i -= 1
		else:
			j = i
			while j >= 0 and s[j] == '*':
				j -= 1
			cnt = x % ((i - j) * k + 1)
			x //= (i - j) * k + 1
			ans += 'b' * cnt
			i = j
	print(''.join(ans[::-1]))


l = input
for o in [0] * int(l()):
	(n, k, x) = map(int, l().split())
	x -= 1
	p = 'a'
	a = [[0, 0]]
	i = 0
	r = ''
	for y in l()[::-1]:
		if y != p:
			p = y
			a += [[0, 0]] * i
			i ^= 1
		a[-1][i] += 1
	for (u, v) in a:
		m = k * v + 1
		r = x % m * 'b' + u * 'a' + r
		x //= m
	print(r)


def solve():
	(n, k, x) = list(map(int, input().split()))
	s = input()
	if '*' not in s:
		print(s)
		return
	stars = [_ for _ in s.split('a') if _]
	expand = [1 + k * len(star) for star in stars]
	prods = [expand[-1]]
	for i in range(1, len(stars)):
		prods += [prods[-1] * expand[len(stars) - i - 1]]
	x -= 1
	counts = []
	for prod in reversed(prods):
		counts += [x // prod]
		x -= prod * (x // prod)
	counts += [x % prods[0]]
	globals().update(locals())
	answer = ''
	i = 1
	j = 0
	while j < len(s):
		if s[j] == 'a':
			answer += 'a'
			j += 1
		else:
			answer += 'b' * counts[i]
			i += 1
			while j < len(s) and s[j] == '*':
				j += 1
	print(answer)
	globals().update(locals())
for _ in range(int(input())):
	solve()


t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	x = x - 1
	s = input().rstrip()
	s = s[::-1]
	ans = []
	i = 0
	while i < n:
		if s[i] == 'a':
			ans.append(s[i])
		else:
			j = i
			c = 0
			while j < n - 1 and s[j] == s[j + 1]:
				c += 1
				j += 1
			h = (c + 1) * k + 1
			ans.append('b' * (x % h))
			x = x // h
			i = j
		i += 1
	print(''.join(ans[::-1]))


from collections import Counter
from sys import *
from collections import defaultdict as dd
from math import *

def inp():
	return int(stdin.readline().strip())

def vinp():
	return map(int, stdin.readline().strip().split())

def linp():
	return list(map(int, stdin.readline().strip().split()))

def sinp(n=1):
	if n == 1:
		return stdin.readline().strip()
	elif n == 2:
		return list(stdin.readline().strip())
	else:
		return list(stdin.readline().split())

def pr(*x, end='\n'):
	print(*x, end=end)

def mod(f, val=1000000007):
	return f % val

def csort(c):
	sorted(c.items(), key=lambda pair: pair[1], reverse=True)

def indc(l, n):
	c = {}
	for i in range(n):
		c[l[i]] = c.get(l[i], []) + [i + 1]
	return c
cou = inp()
for _ in range(cou):
	(n, k, x) = vinp()
	x -= 1
	s = sinp()
	s = s[::-1]
	ans = []
	i = 0
	while i < n:
		if s[i] == 'a':
			ans.append(s[i])
		else:
			j = i
			while j + 1 < n and s[j + 1] == s[i]:
				j += 1
			temp = (j - i + 1) * k + 1
			ans.append('b' * (x % temp))
			x //= temp
			i = j
		i += 1
	pr(''.join(ans[::-1]))


from sys import stdin
input = stdin.readline
rn = lambda : int(input())
rns = lambda : map(int, input().split())
rl = lambda : list(map(int, input().split()))
rs = lambda : input().strip()
YN = lambda x: print('YES') if x else print('NO')
ceil_div = lambda a, b: -(-a // b)
mod = 10 ** 9 + 7
for _ in range(rn()):
	(n, k, x) = rns()
	x -= 1
	s = rs()
	acc = []
	ids = []
	last = s[0]
	c = 0
	for i in range(n + 1):
		if i == n:
			acc.append(c)
			ids.append(last)
		elif s[i] == last:
			c += 1
		else:
			acc.append(c)
			c = 1
			ids.append(last)
			last = s[i]
	ans = ''
	while acc:
		if ids[-1] == 'a':
			ans += acc[-1] * 'a'
			ids.pop()
			acc.pop()
		else:
			m = max(0, x % (acc[-1] * k + 1))
			ans += m * 'b'
			x //= acc[-1] * k + 1
			acc.pop()
			ids.pop()
	print(ans[::-1])


import math
import os
import sys
from decimal import *
from io import BytesIO, IOBase
import threading
from itertools import *
from collections import *
from array import *
import random
M = 10 ** 9 + 7
import heapq
import bisect
from functools import lru_cache
from queue import PriorityQueue
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def inp():
	return sys.stdin.readline().rstrip('\r\n')

def out(var):
	sys.stdout.write(str(var))

def lis():
	return list(map(int, inp().split()))

def stringlis():
	return list(map(str, inp().split()))

def sep():
	return map(int, inp().split())

def strsep():
	return map(str, inp().split())

def fsep():
	return map(float, inp().split())

def inpu():
	return int(inp())

def regularbracket(t):
	p = 0
	for i in t:
		if i == '(':
			p += 1
		else:
			p -= 1
		if p < 0:
			return False
	else:
		if p > 0:
			return False
		else:
			return True

def binarySearchcount(arr, n, key):
	left = 0
	right = n - 1
	count = 0
	while left <= right:
		mid = (right + left) // 2
		if arr[mid] <= key:
			count = mid + 1
			left = mid + 1
		else:
			right = mid - 1
	return count

def binarySearch(arr, n, key):
	left = 0
	right = n - 1
	while left <= right:
		mid = (right + left) // 2
		if arr[mid] == key:
			return mid
		if arr[mid] <= key:
			left = mid + 1
		else:
			right = mid - 1
	return -1

def ternarysearch(arr, n, key):
	(l, r) = (0, n - 1)
	while l <= r:
		mid = (-l + r) // 3 + l
		mid2 = mid + (-l + r) // 3
		if arr[mid] == key:
			return mid
		if arr[mid2] == key:
			return mid2
		if arr[mid] > key:
			r = mid - 1
		elif arr[mid2] < key:
			l = mid2 + 1
		else:
			l = mid + 1
			r = mid2 - 1
	return -1

def reverse1(string):
	pp = ''
	for i in string[::-1]:
		pp += i
	if pp == string:
		return True
	return False

def reverse2(list1):
	l = []
	for i in list1[::-1]:
		l.append(i)
	if l == list1:
		return True
	return False

def sumofdigits(n):
	n = str(n)
	s1 = 0
	for i in n:
		s1 += int(i)
	return s1

def perfect_square(n):
	s = math.sqrt(n)
	if s == int(s):
		return True
	return False

def roman_number(x):
	if x > 15999:
		return
	value = [5000, 4000, 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
	symbol = ['F', 'MF', 'M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']
	roman = ''
	i = 0
	while x > 0:
		div = x // value[i]
		x = x % value[i]
		while div:
			roman += symbol[i]
			div -= 1
		i += 1
	return roman

def soretd(s):
	for i in range(1, len(s)):
		if s[i - 1] > s[i]:
			return False
	return True

def countRhombi(h, w):
	ct = 0
	for i in range(2, h + 1, 2):
		for j in range(2, w + 1, 2):
			ct += (h - i + 1) * (w - j + 1)
	return ct

def countrhombi2(h, w):
	return h * h // 4 * (w * w // 4)

def binpow(a, b):
	if b == 0:
		return 1
	else:
		res = binpow(a, b // 2)
	if b % 2 != 0:
		return res * res * a
	else:
		return res * res

def coprime_to_n(n):
	result = n
	i = 2
	while i * i <= n:
		if n % i == 0:
			while n % i == 0:
				n //= i
			result -= result // i
		i += 1
	if n > 1:
		result -= result // n
	return result

def luckynumwithequalnumberoffourandseven(x, n, a):
	if x >= n and str(x).count('4') == str(x).count('7'):
		a.append(x)
	elif x < 1000000000000.0:
		luckynumwithequalnumberoffourandseven(x * 10 + 4, n, a)
		luckynumwithequalnumberoffourandseven(x * 10 + 7, n, a)
	return a

def luckynum(x, l, r, a):
	if x >= l and x <= r:
		a.append(x)
	if x > r:
		a.append(x)
		return a
	if x < 10000000000.0:
		luckynum(x * 10 + 4, l, r, a)
		luckynum(x * 10 + 7, l, r, a)
	return a

def luckynuber(x, n, a):
	p = set(str(x))
	if len(p) <= 2:
		a.append(x)
	if x < n:
		luckynuber(x + 1, n, a)
	return a

def interact(type, x):
	if type == 'r':
		inp = input()
		return inp.strip()
	else:
		print(x, flush=True)

def findTrailingZeros(n):
	count = 0
	while n >= 5:
		n //= 5
		count += n
	return count

def mergeSort(arr):
	if len(arr) > 1:
		mid = len(arr) // 2
		L = arr[:mid]
		R = arr[mid:]
		mergeSort(L)
		mergeSort(R)
		i = j = k = 0
		while i < len(L) and j < len(R):
			if L[i] < R[j]:
				arr[k] = L[i]
				i += 1
			else:
				arr[k] = R[j]
				j += 1
			k += 1
		while i < len(L):
			arr[k] = L[i]
			i += 1
			k += 1
		while j < len(R):
			arr[k] = R[j]
			j += 1
			k += 1

def solven(p, l, a, b, n, res):
	if p > n or l > 10:
		return
	if p > 0:
		res.add(p)
	solven(p * 10 + a, l + 1, a, b, n)
	solven(p * 10 + b, l + 1, a, b, n)

def subsetsUtil(A, subset, index, d):
	print(*subset)
	s = sum(subset)
	d.append(s)
	for i in range(index, len(A)):
		subset.append(A[i])
		subsetsUtil(A, subset, i + 1, d)
		subset.pop(-1)
	return d

def subsetSums(arr, l, r, d, sum=0):
	if l > r:
		d.append(sum)
		return
	subsetSums(arr, l + 1, r, d, sum + arr[l])
	subsetSums(arr, l + 1, r, d, sum)
	return d

def print_factors(x):
	factors = []
	for i in range(1, x + 1):
		if x % i == 0:
			factors.append(i)
	return factors

def calc(X, d, ans, D):
	if len(X) == 0:
		return
	i = X.index(max(X))
	ans[D[max(X)]] = d
	Y = X[:i]
	Z = X[i + 1:]
	calc(Y, d + 1, ans, D)
	calc(Z, d + 1, ans, D)

def generate(st, s):
	if len(s) == 0:
		return
	if s not in st:
		st.add(s)
		for i in range(len(s)):
			t = list(s).copy()
			t.remove(s[i])
			t = ''.join(t)
			generate(st, t)
	return

def largestincreasingsubsequence(A):
	l = [1] * len(A)
	for i in range(1, len(l)):
		for k in range(i):
			if A[k] <= A[i]:
				l[i] = max(l[i], l[k] + 1)
	return max(l)

def findOR(nums, N):
	prefix_sum = 0
	result = 0
	for i in range(N):
		result |= nums[i]
		prefix_sum += nums[i]
		result |= prefix_sum
	return result

def OR(a, n):
	ans = a[0]
	for i in range(1, n):
		ans |= a[i]
	return ans

def toString(List):
	return ''.join(List)

def permute(a, l, r, p):
	if l == r:
		p.append(toString(a))
	else:
		for i in range(l, r + 1):
			(a[l], a[i]) = (a[i], a[l])
			permute(a, l + 1, r, p)
			(a[l], a[i]) = (a[i], a[l])

def squareRoot(number, precision):
	start = 0
	(end, ans) = (number, 1)
	while start <= end:
		mid = int((start + end) / 2)
		if mid * mid == number:
			ans = mid
			break
		if mid * mid < number:
			start = mid + 1
		else:
			end = mid - 1
	increment = 0.1
	for i in range(0, precision):
		while ans * ans <= number:
			ans += increment
		ans = ans - increment
		increment = increment / 10
	return ans

def countRectangles(l, w):
	squareSide = math.gcd(l, w)
	return int(l * w / (squareSide * squareSide))

def count_same_digit(L, R):
	tmp = 0
	ans = 0
	n = int(math.log10(R) + 1)
	for i in range(0, n):
		tmp = tmp * 10 + 1
		for j in range(1, 10):
			if L <= tmp * j and tmp * j <= R:
				ans += 1
	return ans

def findCrossOver(arr, low, high, x):
	if arr[high] <= x:
		return high
	if arr[low] > x:
		return low
	mid = (low + high) // 2
	if arr[mid] <= x and arr[mid + 1] > x:
		return mid
	if arr[mid] < x:
		return findCrossOver(arr, mid + 1, high, x)
	return findCrossOver(arr, low, mid - 1, x)

def Kclosest(arr, x, k, n, ans):
	l = findCrossOver(arr, 0, n - 1, x)
	r = l + 1
	count = 0
	if arr[l] == x:
		l -= 1
	while l >= 0 and r < n and (count < k):
		if x - arr[l] < arr[r] - x:
			ans.append(arr[l])
			l -= 1
		else:
			ans.append(arr[r])
			r += 1
		count += 1
	while count < k and l >= 0:
		ans.append(arr[l])
		l -= 1
		count += 1
	while count < k and r < n:
		ans.append(arr[r])
		r += 1
		count += 1
	return ans

def dfs(root, nodeVal, nodeConnection, visited):
	leftVal = nodeVal[root][0]
	rightVal = nodeVal[root][1]
	solution = []
	if nodeConnection[root]:
		visited.add(root)
		for i in nodeConnection[root]:
			if i not in visited:
				solution.append(dfs(i, nodeVal, nodeConnection, visited))
		leftMax = 0
		rightMax = 0
		for i in solution:
			(l, r) = i
			leftMax += max(abs(leftVal - l[0]) + l[1], abs(leftVal - r[0]) + r[1])
			rightMax += max(abs(rightVal - l[0]) + l[1], abs(rightVal - r[0]) + r[1])
		return ((leftVal, leftMax), (rightVal, rightMax))
	else:
		return ((leftVal, 0), (rightVal, 0))

def luckynumber(x, n, a):
	if x > 0:
		a.append(x)
	if x > 10 ** 9:
		return a
	elif x < 1000000000000.0:
		luckynumber(x * 10 + 4, n, a)
		luckynumber(x * 10 + 7, n, a)

def lcm(a, b):
	return a * b // math.gcd(a, b)

def query1(l, r):
	if l >= r:
		return -1
	print('?', l + 1, r + 1)
	sys.stdout.flush()
	return int(input()) - 1

def answer(p):
	print('!', p + 1)
	sys.stdout.flush()
	exit()

def buildPrefix(MAX, prefix):
	prime = [1] * (MAX + 1)
	p = 2
	while p * p <= MAX:
		if prime[p] == 1:
			i = p * 2
			while i <= MAX:
				prime[i] = 0
				i += p
		p += 1
	for p in range(2, MAX + 1):
		prefix[p] = prefix[p - 1]
		if prime[p] == 1:
			prefix[p] += 1

def query(L, R, prefix):
	return prefix[R] - prefix[L - 1]

def maxSubArraySum(a, size):
	max_so_far = a[0]
	curr_max = a[0]
	for i in range(1, size):
		curr_max = max(a[i], curr_max + a[i])
		max_so_far = max(max_so_far, curr_max)
	return max_so_far

def solvepp(n, k):
	if n == 1 and k == 1:
		return 0
	mid = 2 ** (n - 1) // 2
	if k <= mid:
		return solvepp(n - 1, k)
	else:
		return solvepp(n - 1, k - mid) == 0

def solvr(s, p):
	if len(s) == 0:
		print(p, end=' ')
		return
	op1 = p
	op2 = p + s[0]
	s = s[1:]
	solvr(s, op1)
	solvr(s, op2)
	return

def paranthesis(n, m, ans, l):
	if n == 0 and m == 0:
		print(ans)
		return
	if n != 0:
		op1 = ans + '('
		paranthesis(n - 1, m, op1, l)
	if m > n:
		op2 = ans + ')'
		paranthesis(n, m - 1, op2, l)

def rse(arr, n):
	stack = []
	ans = []
	for i in range(n - 1, -1, -1):
		if len(stack) == 0:
			ans.append(n)
		else:
			while len(stack) != 0:
				if stack[-1][0] >= arr[i]:
					stack.pop()
				else:
					break
			if len(stack) == 0:
				ans.append(n)
			else:
				ans.append(stack[-1][1])
		stack.append([arr[i], i])
	ans.reverse()
	return ans

def lse(arr, n):
	stack = []
	ans = []
	for i in range(n):
		if len(stack) == 0:
			ans.append(-1)
		else:
			while len(stack) != 0:
				if stack[-1][0] >= arr[i]:
					stack.pop()
				else:
					break
			if len(stack) == 0:
				ans.append(-1)
			else:
				ans.append(stack[-1][1])
		stack.append([arr[i], i])
	return ans

def mah(arr):
	max1 = 0
	p = rse(arr, len(arr))
	q = lse(arr, len(arr))
	for i in range(len(arr)):
		a = (p[i] - q[i] - 1) * arr[i]
		max1 = max(a, max1)
	return max1

def lcs(s, r):
	rr = len(r)
	ss = len(s)
	l = [[0] * (rr + 1) for i in range(ss + 1)]
	for i in range(1, ss + 1):
		for j in range(1, rr + 1):
			if s[i - 1] == r[j - 1]:
				l[i][j] = l[i - 1][j - 1] + 1
			else:
				l[i][j] = max(l[i - 1][j], l[i][j - 1])
	return l[ss][rr]

def subsetsum(arr, sum, len):
	dp = [[False] * (sum + 1) for i in range(len + 1)]
	for i in range(len + 1):
		dp[i][0] = True
	for i in range(1, len + 1):
		for j in range(1, sum + 1):
			if arr[i - 1] > j:
				dp[i][j] = dp[i - 1][j]
			else:
				dp[i][j] = dp[i - 1][j] or dp[i - 1][j - arr[i - 1]]
	return dp[len][sum]

def matrixmincost(cost, n, m):
	dp = [[0 for x in range(m)] for x in range(n)]
	for i in range(n):
		for j in range(m):
			if i == 0 and j == 0:
				dp[i][j] = cost[i][j]
			elif i == 0 and j != 0:
				dp[i][j] = dp[i][j - 1] + cost[i][j]
			elif j == 0 and i != 0:
				dp[i][j] = dp[i - 1][j] + cost[i][j]
			else:
				dp[i][j] = cost[i][j] + min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])
	return dp[n - 1][m - 1]

def coinchange(n, arr, len1):
	dp = [0] * (n + 1)
	dp[0] = 1
	for i in range(len1):
		for j in range(arr[i], n + 1):
			dp[j] += dp[j - arr[i]]
	return dp[n]

class Graph(object):

	def __init__(self, vertices):
		self.graph = defaultdict(list)
		self.V = vertices

	def addEdge(self, u, v):
		self.graph[u].append(v)
		self.graph[v].append(u)

	def connectedComponents(self):
		unvisited = set(range(self.V))
		queue = deque()
		count = 0
		while len(unvisited) > 0:
			count += 1
			v = next(iter(unvisited))
			unvisited.remove(v)
			queue.append(v)
			while len(queue) > 0:
				v = queue.popleft()
				for w in self.graph[v]:
					if w in unvisited:
						unvisited.remove(w)
						queue.append(w)
		return count

def maxSumIS(arr, n):
	msis = arr.copy()
	for i in range(1, n):
		for j in range(i):
			if arr[i] > arr[j] and msis[i] < msis[j] + arr[i]:
				msis[i] = msis[j] + arr[i]
	c = max(msis)
	p = 5
	return c

def binarysearch2(arr, target):
	lo = 0
	hi = len(arr) - 1
	while lo <= hi:
		mid = (lo + hi) // 2
		if arr[mid] == target:
			if mid != len(arr) - 1:
				if arr[mid + 1] != target:
					return mid
				else:
					lo += 1
			else:
				return mid
			continue
		if arr[mid] > target:
			hi = mid - 1
		else:
			lo = mid + 1

def nge(arr, n):
	stack = []
	ans = []
	for i in range(n - 1, -1, -1):
		if len(stack) == 0:
			ans.append(-1)
		else:
			while len(stack) > 0:
				if stack[-1][0] < arr[i]:
					stack.pop()
				else:
					break
			if len(stack) == 0:
				ans.append(-1)
			else:
				ans.append(stack[-1][1])
		stack.append([arr[i], i])
	ans.reverse()
	return ans

def nse(arr, n):
	stack = []
	ans = []
	for i in range(n - 1, -1, -1):
		if len(stack) == 0:
			ans.append(-1)
		else:
			while len(stack) > 0:
				if stack[-1][0] > arr[i]:
					stack.pop()
				else:
					break
			if len(stack) == 0:
				ans.append(-1)
			else:
				ans.append(stack[-1][1])
		stack.append([arr[i], i])
	ans.reverse()
	return ans

def alperm(nums, path, result):
	if not nums:
		result.add(tuple(path))
		return
	for i in range(0, len(nums)):
		alperm(nums[:i] + nums[i + 1:], path + [nums[i]], result)
	return result

def minsum(arr, n, m, res, l):
	if n == 1 and m == 1:
		res += arr[0][0]
		l.append(res)
	else:
		if n != 1:
			p = res + arr[n - 1][m - 1]
			minsum(arr, n - 1, m, p, l)
		if m != 1:
			p = res + arr[n - 1][m - 1]
			minsum(arr, n, m - 1, p, l)
	return min(l)

def catalan(n):
	if n == 0 or n == 1:
		return 1
	catalan = [0] * (n + 1)
	catalan[0] = 1
	catalan[1] = 1
	for i in range(2, n + 1):
		for j in range(i):
			catalan[i] += catalan[j] * catalan[i - j - 1]
	return catalan[n]

def find_shortest_path(graph, start, end, path):
	path = path + [start]
	if start == end:
		return path
	if start not in graph:
		return None
	shortest = None
	for node in graph[start]:
		if node not in path:
			newpath = find_shortest_path(graph, node, end, path)
			if newpath:
				if not shortest or len(newpath) < len(shortest):
					shortest = newpath
	return shortest

def test(n, d):
	a = random.randint(1, n - 2)
	p = pow(a, d, n)
	if p == 1 or p == n - 1:
		return True
	while d != n - 1:
		d *= 2
		p = pow(p, 2, n)
		if p == n - 1:
			return True
	return False

def isprime(n):
	if n == 1:
		return False
	if n == 2:
		return True
	if n == 3:
		return True
	d = n - 1
	while d % 2 == 0:
		d //= 2
	for i in range(5):
		if test(n, d) == False:
			return False
	return True

def muin(a, m):
	(x, y, mo) = (1, 0, m)
	if m == 1:
		return 0
	while m > 0:
		(x, y) = (y, x - a // m * y)
		(a, m) = (m, a % m)
	if x < 0:
		return mo + x
	else:
		return x

def good(l, c):
	ch = chr(c)
	if len(l) == 1:
		return 1 if ch != l[0] else 0
	k = len(l) // 2
	lm = k - l[:k].count(ch) + good(l[k:], c + 1)
	rm = k - l[k:].count(ch) + good(l[:k], c + 1)
	return min(lm, rm)

def facto(fact):
	(fact[0], fact[1]) = (1, 1)
	for i in range(2, 10 ** 5 + 1):
		fact[i] = fact[i - 1] * i % M

def comb(n, r, fact):
	return fact[n] * pow(fact[n - r] * fact[r], M - 2, M) % M

def numberToBase(n, b):
	if n == 0:
		return 0
	digits = []
	while n:
		digits.append(n % b)
		n //= b
	return sum(digits)

def sieveoferonthesis(prime, maxn):
	(prime[0], prime[1]) = (False, False)
	for i in range(2, int(math.sqrt(maxn)) + 1):
		if prime[i] == True:
			for j in range(i * i, maxn + 1, i):
				prime[j] = False

def sieve(spf):
	MAXN = 100001
	spf[1] = 1
	for i in range(2, MAXN):
		spf[i] = i
	for i in range(4, MAXN, 2):
		spf[i] = 2
	for i in range(3, math.ceil(math.sqrt(MAXN))):
		if spf[i] == i:
			for j in range(i * i, MAXN, i):
				if spf[j] == j:
					spf[j] = i

def getFactorization(x, spf):
	ret = list()
	while x != 1:
		ret.append(spf[x])
		x = x // spf[x]
	return ret

def main():
	tt = 1
	tt = inpu()
	for _ in range(tt):
		(n, k, x) = sep()
		s = inp()
		res = []
		cnt = 0
		for i in s:
			if i == '*':
				cnt += 1
			else:
				if cnt != 0:
					res.append(cnt * k)
				res.append('a')
				cnt = 0
		if cnt:
			res.append(cnt * k)
		pro = [0] * (len(res) + 1)
		cnt = 1
		for i in range(len(res) - 1, -1, -1):
			if res[i] == 'a':
				continue
			pro[i] = cnt
			if cnt > 10 ** 18:
				continue
			cnt *= res[i] + 1
		x -= 1
		for i in range(len(res)):
			if res[i] == 'a':
				continue
			k = x // pro[i]
			res[i] = 'b' * k
			x -= k * pro[i]
		print(''.join(res))
main()


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
a = int(input())
for i in range(a):
	(n, k, x) = map(int, input().split())
	s = input()
	x -= 1
	base = k
	cnt = 0
	flag = 1
	ans = []
	total = 0
	ori = []
	g1 = 1
	gt = 0
	base = k
	q = pow(10, 20)
	for i in range(len(s) - 1, -1, -1):
		gt = min(gt, q)
		base = min(base, q)
		g1 = min(g1, q)
		if s[i] == '*' and flag == 0:
			ans.append([i, min(base, q)])
			ori.append(g1)
			gt += base
		if s[i] == 'a' and flag == 0:
			base = (gt + 1) * k
			g1 = gt + 1
			flag = 1
		if s[i] == 'a' and flag == 1:
			continue
		if s[i] == '*' and flag == 1:
			gt += base
			ans.append([i, base])
			ori.append(g1)
			flag = 0
	ans = ans[::-1]
	ori = ori[::-1]
	g1 = []
	m3 = []
	for i in range(len(ans)):
		idx = ans[i][0]
		if x >= ans[i][1]:
			g1.append([idx, k])
			x -= ans[i][1]
			continue
		elif x < ori[i]:
			g1.append([idx, 0])
			continue
		m = x // ori[i]
		g1.append([idx, m])
		x -= m * ori[i]
	fin = []
	i1 = 0
	for i in range(len(s)):
		if s[i] == 'a':
			fin.append('a')
		else:
			for j in range(g1[i1][1]):
				fin.append('b')
			i1 += 1
	print(''.join(map(str, fin)))


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()[:-1]
	alls = True
	vals = [0]
	aval = [0]
	for ch in s:
		if ch == 'a':
			alls = False
			if vals[-1] > 0:
				vals.append(0)
			aval[-1] += 1
		else:
			if aval[-1] > 0:
				aval.append(0)
			vals[-1] += 1
	if vals[-1] == 0:
		vals.pop(-1)
	if alls:
		print('b' * x)
	else:
		bval = [0 for i in range(len(vals))]
		x -= 1
		for i in range(len(vals) - 1, -1, -1):
			bval[i] = x % (vals[i] * k + 1)
			x //= vals[i] * k + 1
		ans = ''
		if s[0] == '*':
			for i in range(len(aval)):
				ans += bval[i] * 'b' + aval[i] * 'a'
		else:
			for i in range(len(bval)):
				ans += aval[i] * 'a' + bval[i] * 'b'
		if len(aval) > len(bval):
			ans += 'a' * aval[-1]
		if len(bval) > len(aval):
			ans += 'b' * bval[-1]
		print(ans)


def main():
	t = int(input())
	allans = []
	for _ in range(t):
		(n, k, x) = readIntArr()
		x -= 1
		s = input()
		cnts = 0
		arr = []
		for (i, c) in enumerate(s):
			if c == 'a':
				if cnts > 0:
					arr.append(cnts * k)
					cnts = 0
				arr.append(c)
			else:
				cnts += 1
		if cnts > 0:
			arr.append(cnts * k)
		numIdxes = []
		cntsAtIdxes = []
		for (i, c) in enumerate(arr):
			if type(c) == int:
				numIdxes.append(i)
				cntsAtIdxes.append(c)
		m = len(numIdxes)
		suffixProducts = [1] * m
		for i in range(m - 2, -1, -1):
			suffixProducts[i] = suffixProducts[i + 1] * (cntsAtIdxes[i + 1] + 1)
		requiredCnts = [0] * m
		for i in range(m):
			for j in range(cntsAtIdxes[i], -1, -1):
				if j * suffixProducts[i] <= x:
					requiredCnts[i] = j
					x -= j * suffixProducts[i]
					break
		ans = []
		j = 0
		for c in arr:
			if c == 'a':
				ans.append('a')
			else:
				for __ in range(requiredCnts[j]):
					ans.append('b')
				j += 1
		allans.append(''.join(ans))
	multiLineArrayPrint(allans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(defaultValFactory, dimensionArr):
	dv = defaultValFactory
	da = dimensionArr
	if len(da) == 1:
		return [dv() for _ in range(da[0])]
	else:
		return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(a, b, c):
	print('? {} {} {}'.format(a, b, c))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ansArr):
	print('! {}'.format(' '.join([str(x) for x in ansArr])))
	sys.stdout.flush()
inf = float('inf')
from math import gcd, floor, ceil
import math
for _abc in range(1):
	main()


for z in range(int(input())):
	(n, k, x) = map(int, input().split())
	x -= 1
	s = input()[::-1]
	r = []
	i = 0
	while i <= n - 1:
		if s[i] == 'a':
			r.append(s[i])
		else:
			j = i
			while j + 1 <= n - 1 and s[j + 1] == s[i]:
				j += 1
			cur = (j - i + 1) * k + 1
			r.append('b' * (x % cur))
			x //= cur
			i = j
		i += 1
	print(''.join(r[::-1]))


def merge(string, k):
	arr = []
	mrgstring = []
	prevstar = False
	temp = 0
	for i in range(1, len(string) + 1):
		if string[-1 * i] == '*':
			prevstar = True
			temp += 1
		else:
			if prevstar:
				mrgstring.append('*')
				arr.append(k * temp + 1)
				temp = 0
				prevstar = False
			mrgstring.append('a')
	if prevstar:
		mrgstring.append('*')
		arr.append(k * temp + 1)
	mrgstring.reverse()
	mrgstring = ''.join(mrgstring)
	return (arr, mrgstring)

def f(string, arr, x):
	farr = []
	x = x - 1
	for i in arr:
		if i == 0:
			farr.append(0)
		else:
			farr.append(x % i)
			x = int(x // i)
	farr.reverse()
	temp = ''
	j = 0
	for i in string:
		if i == '*':
			temp += 'b' * int(farr[j])
			j += 1
		else:
			temp += 'a'
	print(temp)
t = int(input())
for i in range(t):
	(n, k, x) = list(map(int, input().split(' ')))
	q = input()
	(arr, mstr) = merge(q, k)
	f(mstr, arr, x)


T = int(input())

def preprocess(s):
	s_new = s[0]
	for i in range(1, len(s)):
		if s[i] == 'a':
			s_new += 'a'
		elif s[i - 1] != s[i] == '*':
			s_new += '*'
	return s_new
for t in range(T):
	(n, k, x) = map(int, input().split())
	s1 = input()
	stars = s1.split('a')
	s = list(s1)
	b_add = x - 1
	number = []
	for i in stars:
		if len(i) != 0:
			number.append(len(i) * k + 1)
	number.append(1)
	new_num = number[1:]
	prod = 1
	new_number = []
	for i in range(len(new_num) - 1, -1, -1):
		prod *= new_num[i]
		new_number.append(prod)
	new_number = new_number[::-1]
	no_b = []
	for i in new_number:
		no_b.append(b_add // i)
		b_add -= b_add // i * i
	no_b_rev = no_b[::-1]
	ps = preprocess(s1)
	answer = ''
	for i in ps:
		if i == 'a':
			answer += 'a'
		else:
			answer += 'b' * no_b_rev.pop()
	print(answer)


t = int(input())
for i in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	(aa, ab) = ([], [])
	if s[0] == '*':
		aa.append(0)
	c = 0
	for j in range(n):
		if s[j] == 'a':
			c += 1
		elif c != 0:
			aa.append(c)
			c = 0
	if c != 0:
		aa.append(c)
	c = 0
	for j in range(n):
		if s[j] == '*':
			c += 1
		elif c != 0:
			ab.append(c)
			c = 0
	if ab != 0:
		ab.append(c)
	y = x
	y -= 1
	nb = ab[:]
	for i in range(len(ab) - 1, -1, -1):
		nb[i] = y % (ab[i] * k + 1)
		y = y // (ab[i] * k + 1)
	for i in range(len(aa)):
		print('a' * aa[i], end='')
		if i < len(nb):
			print('b' * nb[i], end='')
	print('')


for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	x -= 1
	s = input()[::-1]
	l1 = s.split('a')
	i = 0
	ans = []
	for i in range(len(l1)):
		ans.append('a')
		temp = len(l1[i]) * k + 1
		ans.append('b' * (x % temp))
		x = x // temp
	ans.pop(0)
	print(''.join(ans[::-1]))


T = int(input())
while T > 0:
	(n, k, x) = map(int, input().split())
	arr = input()
	total = 1
	store = [1]
	count = 0
	for i in range(n - 1, -1, -1):
		if arr[i] == '*':
			count += 1
		elif count > 0:
			total = count * k * total + total
			if total >= x:
				break
			store.append(total)
			count = 0
	have = []
	cur = x - 1
	for i in range(len(store) - 1, -1, -1):
		have.append(cur // store[i])
		cur = cur % store[i]
	i = n - 1
	res = []
	index = len(have) - 1
	while i >= 0:
		if arr[i] == '*':
			if index >= 0:
				res += ['b'] * have[index]
				index -= 1
			while i >= 0 and arr[i] == '*':
				i -= 1
		else:
			res.append('a')
			i -= 1
	res.reverse()
	print(''.join(res))
	T -= 1


t = int(input())
while t:
	t -= 1
	(n, k, x) = map(int, input().split())
	s = input()
	i = 0
	holes = []
	ans = []
	while i < len(s):
		while i < len(s) and s[i] == 'a':
			i += 1
		f = 0
		while i < len(s) and s[i] == '*':
			i += 1
			f += 1
		holes.append(f * k + 1)
	x -= 1
	for i in range(len(holes)):
		pro = 1
		for j in range(i + 1, len(holes)):
			pro *= holes[j]
		ans.append(x // pro)
		x %= pro
	i = 0
	ptr = 0
	res = ''
	while i < len(s):
		while i < len(s) and s[i] == 'a':
			res += 'a'
			i += 1
		f = 0
		while i < len(s) and s[i] == '*':
			i += 1
			f += 1
		if f:
			res += ans[ptr] * 'b'
			ptr += 1
	print(res)


for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	l = []
	d = {}
	n_a = 0
	n_b = 0
	prev = None
	for char in s:
		if char == '*':
			n_b += k
			if prev != '*':
				l.append(['b', 0, k])
				d[len(l) - 1] = l[-1]
			else:
				l[-1][-1] += k
		else:
			n_a += 1
			if prev != 'a':
				l.append(['a', 1, 1])
			else:
				l[-1][1] += 1
				l[-1][2] += 1
		prev = char
	marr = [d[i][-1] for i in sorted(d.keys(), reverse=True)]
	barr = [0] * len(marr)
	i = 0
	x -= 1
	while x:
		(x, r) = divmod(x, marr[i] + 1)
		barr[i] = r % (marr[i] + 1)
		i += 1
		if i == len(barr):
			break
	for (n_b, key) in zip(barr, sorted(d.keys(), reverse=True)):
		d[key][1] = n_b
	ans = ''
	for item in l:
		ans += item[0] * item[1]
	print(ans)


import sys
import bisect
from bisect import bisect_left as lb
from bisect import bisect_right as rb
input_ = lambda : sys.stdin.readline().strip('\r\n')
from math import log
from math import gcd
from math import atan2, acos
from random import randint
sa = lambda : input_()
sb = lambda : int(input_())
sc = lambda : input_().split()
sd = lambda : list(map(int, input_().split()))
sflo = lambda : list(map(float, input_().split()))
se = lambda : float(input_())
sf = lambda : list(input_())
flsh = lambda : sys.stdout.flush()
sys.setrecursionlimit(3 * 10 ** 5)
mod = 10 ** 9 + 7
mod1 = 998244353
gp = []
cost = []
dp = []
mx = []
ans1 = []
ans2 = []
special = []
specnode = []
a = 0
kthpar = []

def dfs2(root, par):
	if par != -1:
		dp[root] = dp[par] + 1
	for i in range(1, 20):
		if kthpar[root][i - 1] != -1:
			kthpar[root][i] = kthpar[kthpar[root][i - 1]][i - 1]
	for child in gp[root]:
		if child == par:
			continue
		kthpar[child][0] = root
		dfs(child, root)
ans = 0
a = []
(n, k) = (0, 0)
b = []
vis = []
tot = 0
time = []
time1 = []
adj = []
mx = -1
eps = 1e-07
x = 0
pref = []
lvl = []
gp = []
ans = []
f = 0
w = []

def dfs(i, prod, rem, n):
	if rem == 0:
		while i < len(n):
			prod *= int(n[i])
			i += 1
		return prod
	if i == len(n):
		return prod
	mx = 0
	for j in range(9 - int(n[i])):
		mx = max(dfs(i + 1, (int(n[i]) + min(j, rem)) * prod, rem - min(j, rem), n), mx)
	return mx

class Disjoint_SU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.size = [1 for i in range(n)]

	def lake_de(self, a):
		if a == self.parent[a]:
			return a
		self.parent[a] = self.lake_de(self.parent[a])
		return self.parent[a]

	def jod(self, a, b):
		x = self.lake_de(a)
		y = self.lake_de(b)
		if x == y:
			return True
		if self.size[x] > self.size[y]:
			self.size[x] += self.size[y]
			self.parent[y] = x
		else:
			self.size[y] += self.size[x]
			self.parent[x] = y
		return False

def hnbhai(tc):
	(n, k, x) = sd()
	a = sa()
	stck = []
	tot = 0
	are = []
	for i in range(n):
		if a[i] == '*':
			tot += 1
		else:
			if tot != 0:
				are.append(['b', k * tot + 1])
			tot = 0
			are.append(['a', 1])
	if tot != 0:
		are.append(['b', k * tot + 1])
	suffix = [1] * (n + 1)
	for i in range(len(are) - 1, -1, -1):
		suffix[i] = suffix[i + 1] * are[i][1]
		suffix[i] = min(10 ** 19, suffix[i])
	ans = []
	for i in range(len(are)):
		if are[i][0] == 'b':
			for j in range(are[i][1]):
				if (j + 1) * suffix[i + 1] >= x:
					ans.append('b' * j)
					x -= j * suffix[i + 1]
					break
		else:
			ans.append(are[i][0])
	print(''.join(ans))
	return
for _ in range(sb()):
	hnbhai(_ + 1)


I = input
for _ in [0] * int(I()):
	(n, k, x) = map(int, I().split())
	x -= 1
	p = 'a'
	a = [0]
	r = [0]
	for y in I():
		if y != p:
			p = y
			a += (0,)
		a[-1] += 1
	for y in a[1::2][::-1]:
		m = 1 + k * y
		r = [x % m] + r
		x //= m
	print(''.join((x * 'a' + y * 'b' for (x, y) in zip(a[::2], r))))


for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	a = []
	for c in s:
		if len(a) > 0 and a[-1][0] == c:
			a[-1][1] += 1
		else:
			a.append([c, 1])
	a.append(['', 0, 1])
	a = a[::-1]
	for i in range(1, len(a)):
		if a[i - 1][0] == '*':
			a[i].append(a[i - 1][2] * (a[i - 1][1] * k + 1))
		else:
			a[i].append(a[i - 1][2])
	a = a[::-1]
	answer = ''
	x -= 1
	for item in a[:-1]:
		if item[0] == 'a':
			answer += 'a' * item[1]
		else:
			answer += 'b' * (x // item[2])
			x %= item[2]
	print(answer)


I = input
for _ in [0] * int(I()):
	(n, k, x) = map(int, I().split())
	x -= 1
	p = 'a'
	a = [[0, 0]]
	i = 0
	r = ''
	for y in I()[::-1]:
		if y != p:
			p = y
			a += [[0, 0]] * i
			i ^= 1
		a[-1][i] += 1
	for (u, v) in a:
		m = k * v + 1
		r = x % m * 'b' + u * 'a' + r
		x //= m
	print(r)


for _ in range(int(input())):
	(n, k, x) = list(map(int, input().split()))
	s = input()
	short = ''
	for c in s:
		if not short.endswith('*') or c == 'a':
			short += c
	stars_sequences = list(filter(None, s.split('a')))
	stars_count = [i.count('*') * k + 1 for i in stars_sequences]
	res = ''
	x = x - 1
	digits = []
	for el in stars_count[::-1]:
		digits.append(x % el)
		x //= el
	digits = digits[::-1]
	count = 0
	for el in short:
		if el == '*':
			res += 'b' * digits[count]
			count += 1
		else:
			res += 'a'
	print(res)


import re

def main():
	(n, k, x) = map(int, input().split())
	x = x - 1
	s = input()
	if k == 0:
		print('a' * s.count('a'))
		return
	arr = [0]
	for i in range(n):
		if s[i] == 'a':
			arr.append(0)
		else:
			arr[-1] += k
	arr = [i for i in arr if i]
	res = [0] * len(arr)
	for i in range(len(arr) - 1, -1, -1):
		res[i] = x % (arr[i] + 1)
		x = x // (arr[i] + 1)
	s = re.sub('\\*+', '*', s)
	c = 0
	sn = ''
	for i in range(len(s)):
		if s[i] == 'a':
			sn += 'a'
		else:
			sn += 'b' * res[c]
			c += 1
	print(sn)
t = int(input())
for i in range(t):
	main()


import sys
import io
import math
import collections
import decimal
import itertools
import bisect
import heapq

def input():
	return sys.stdin.readline()[:-1]
INF = 10 ** 10

def solve(N, K, X, S):
	X -= 1
	n = 0
	result = []
	for c in ('-' + S)[::-1]:
		if c == '*':
			n += 1
		else:
			v = X % (K * n + 1)
			result.append('b' * v)
			X //= K * n + 1
			n = 0
			if c == 'a':
				result.append('a')
	return ''.join(reversed(result))
T0 = int(input())
for _ in range(T0):
	(N, K, X) = map(int, input().split())
	S = input()
	print(solve(N, K, X, S))


import sys
from bisect import bisect_left as lb
from bisect import bisect_right as rb
from collections import deque
from queue import PriorityQueue as pq
from math import gcd
input_ = lambda : sys.stdin.readline().strip('\r\n')
ii = lambda : int(input_())
il = lambda : list(map(int, input_().split()))
ilf = lambda : list(map(float, input_().split()))
lii = lambda : list(map(int, list(ip())))
ip = lambda : input_()
fi = lambda : float(input_())
ap = lambda ab, bc, cd: ab[bc].append(cd)
li = lambda : list(input_())
pr = lambda x: print(x)
prinT = lambda x: print(x)
f = lambda : sys.stdout.flush()
inv = lambda x: pow(x, mod - 2, mod)
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
mod = 10 ** 9 + 7
mod1 = 998244353
for _ in range(ii()):
	(n, k, x) = il()
	s = list(ip())
	t = 0
	a = []
	for i in range(n):
		if s[i] == '*':
			t += 1
		else:
			if t != 0:
				a.append(['b', k * t + 1])
			t = 0
			a.append(['a', 1])
	if t != 0:
		a.append(['b', k * t + 1])
	s = [1 for i in range(n + 1)]
	for i in range(len(a) - 1, -1, -1):
		s[i] = s[i + 1] * a[i][1]
		s[i] = min(10 ** 19, s[i])
	ans = []
	for i in range(len(a)):
		if a[i][0] == 'b':
			for j in range(a[i][1]):
				if (j + 1) * s[i + 1] >= x:
					ans.append('b' * j)
					x -= j * s[i + 1]
					break
		else:
			ans.append(a[i][0])
	print(''.join(ans))


for i in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	l = []
	c = 0
	for i in s:
		if i == 'a' and c != 0:
			l += [c]
			c = 0
		elif i == 'a':
			c = 0
		else:
			c += 1
	if c > 0:
		l += [c]
	a = s.replace('*', ' ').split()
	j = ''
	F = 0
	if s[0] == 'a':
		j += a[0]
		F = 1
	x -= 1
	for i in range(len(l) - 1):
		j += 'b' * (x // eval('*'.join([str(l[x] * k + 1) for x in range(i + 1, len(l))])))
		x %= eval('*'.join([str(l[x] * k + 1) for x in range(i + 1, len(l))]))
		if i + F < len(a):
			j += a[i + F]
	print(j + 'b' * x + ['', a[-1]][s[-1] == 'a' and s.count('*') > 0])


t = int(input())
for T in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	x -= 1
	cnt = 0
	v = []
	cntqq = 0
	for i in s:
		if i == '*':
			cnt += 1
			cntqq = 1
		elif cnt != 0:
			v.append(cnt * k + 1)
			cnt = 0
	if cnt != 0:
		v.append(cnt * k + 1)
	p = [1] * len(v)
	if cntqq:
		p[-1] = v[-1]
	for i in range(len(v) - 2, -1, -1):
		p[i] = p[i + 1] * v[i]
	p.append(0)
	flag = 1
	q = ''
	for i in range(len(s)):
		if s[i] == 'a':
			q += 'a'
		elif len(q) == 0:
			q += '*'
		elif q[-1] != '*':
			q += '*'
	s = q
	for i in range(len(s)):
		if s[i] == 'a':
			print('a', end='')
		elif p[flag] == 0:
			print('b' * x, end='')
			x = 0
		elif x == 0:
			x = 0
		else:
			while x - p[flag] >= 0 and x > 0:
				x -= p[flag]
				print('b', end='')
			flag += 1
	print()


def main():
	(n, k, x) = map(int, input().split())
	s = input()
	if len(set(s)) == 1:
		return s
	arr = []
	curr = 0
	for i in range(n):
		if s[i] == '*':
			curr += 1
		if s[i] == 'a' and curr > 0:
			arr.append(k * curr + 1)
			curr = 0
	if curr > 0:
		arr.append(k * curr + 1)
	l = len(arr)
	aux = [0] * l
	c = s[0]
	for i in range(1, n):
		if s[i] == '*' and c[-1] != '*':
			c += '*'
		elif s[i] == 'a':
			c += 'a'
	prod = 1
	arr = arr[::-1]
	for i in range(l):
		prod = arr[i] * prod
		if prod >= x:
			break
	extra = arr[:i + 1]
	extra = extra[::-1]
	lol = []
	for j in range(i + 1):
		prod = prod // extra[j]
		a = (x - 1) // prod
		lol.append(a)
		x -= a * prod
	final = [0] * (l - (i + 1)) + lol
	ans = ''
	i = 0
	for k in c:
		if k == 'a':
			ans += 'a'
		else:
			for j in range(final[i]):
				ans += 'b'
			i += 1
	return ans
for _ in range(int(input())):
	print(main())


import sys
input = sys.stdin.readline

def inp():
	return int(input())

def inlt():
	return list(map(int, input().split()))

def insr():
	s = input()
	return list(s[:len(s) - 1])

def invr():
	return map(int, input().split())
from collections import Counter
t = inp()
for _ in range(t):
	(n, k, x) = invr()
	s = insr()
	ss = [s[0]]
	for (i, c) in enumerate(list(s)[1:]):
		if c == 'a':
			ss.append(c)
			continue
		if c == ss[-1]:
			continue
		else:
			ss.append(c)
	A = []
	t = 0
	if s[0] == '*':
		t = 1
	for (i, c) in enumerate(list(s)[1:]):
		if c == '*' and s[i] == '*':
			t += 1
		if c == '*' and s[i] != '*':
			t = 1
		if c == 'a' and s[i] == '*':
			A.append(t)
	if s[-1] == '*':
		A.append(t)
	res_cnt = []
	x -= 1
	for i in A[::-1]:
		res_cnt.append(x % (i * k + 1))
		x //= i * k + 1
	res = ''
	for c in ss:
		if c == '*':
			num = res_cnt.pop()
			res += 'b' * num
		else:
			res += 'a'
	print(res)


from __future__ import print_function
from math import *
from collections import deque
import os
import sys
from io import BytesIO, IOBase

def main():
	pass
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
mod = 10 ** 9 + 7

def inp():
	return int(input())

def inlt():
	return list(map(int, input().split()))

def insr():
	s = input()
	return list(s[:len(s)])

def invr():
	return map(int, input().split())
for _ in range(inp()):
	(n, k, x) = invr()
	l = insr()
	if l == ['*'] * n:
		print('b' * x)
		continue
	if n == 1:
		print('a')
		continue
	y = []
	if l[0] != 'a':
		y.append(-1)
	for i in range(n):
		if l[i] == 'a':
			y.append(i)
	if l[-1] != 'a':
		y.append(n)
	ans = ['a']
	xx = len(y)
	pr = [1] * xx
	for i in range(xx - 2, -1, -1):
		mid = y[i + 1] - y[i] - 1
		pr[i - 1] = mid * k * pr[i] + pr[i]
	for i in range(xx - 1):
		while x > pr[i]:
			x -= pr[i]
			ans.append('b')
		ans.append('a')
	if l[-1] != 'a':
		ans.pop()
	if l[0] != 'a':
		ans = ans[1:]
	print(''.join((i for i in ans)))


import sys
from collections import deque
import math
from bisect import bisect_left
from functools import cmp_to_key

def II():
	return int(sys.stdin.readline())

def LI():
	return list(map(int, sys.stdin.readline().split()))

def MI():
	return map(int, sys.stdin.readline().split())

def SI():
	return sys.stdin.readline().strip()

def FACT(n, mod):
	s = 1
	facts = [1]
	for i in range(1, n + 1):
		s *= i
		s %= mod
		facts.append(s)
	return facts[n]

def C(n, k, mod):
	return FACT(n, mod) * pow(FACT(k, mod) * FACT(n - k, mod) % mod, mod - 2, mod) % mod

def lcm(a, b):
	return abs(a * b) // math.gcd(a, b)
for _ in range(II()):
	(n, k, x) = MI()
	s = list(SI())
	if s[0] == 'a':
		newS = ['a']
		temp = [0]
	else:
		newS = ['*']
		temp = [k + 1]
	for i in range(1, n):
		if s[i] == 'a':
			temp.append(0)
			newS.append('a')
		elif newS[-1] == '*':
			temp[-1] += k
		else:
			temp.append(k + 1)
			newS.append('*')
	d = [0 for i in range(len(s))]
	cur = 0
	start = 0
	s = newS
	for i in range(len(s) - 1, -1, -1):
		if cur >= x:
			start = i + 1
			break
		if s[i] == '*':
			d[i] = cur
			if cur == 0:
				cur = temp[i]
			else:
				cur *= temp[i]
	for i in range(start, len(s)):
		if s[i] == '*':
			if d[i] != 0:
				tt = math.ceil(x / d[i]) - 1
				s[i] = 'b' * tt
				x -= tt * d[i]
			else:
				if x == 0:
					x = temp[i]
				s[i] = 'b' * (x - 1)
				x = 0
	for i in range(len(s)):
		if s[i] == '*':
			s[i] = ''
	print(''.join(s))


import os
import sys
import math
from io import BytesIO, IOBase
import io
from fractions import Fraction
import collections
from itertools import permutations
from collections import defaultdict
from collections import deque
from collections import Counter
import threading
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class SegmentTree:

	def __init__(self, data, default=10 ** 18, func=lambda a, b: min(a, b)):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class SegmentTree1:

	def __init__(self, data, default=0, func=lambda a, b: a + b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)
MOD = 10 ** 9 + 7

class Factorial:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorials = [1, 1]
		self.invModulos = [0, 1]
		self.invFactorial_ = [1, 1]

	def calc(self, n):
		if n <= -1:
			print('Invalid argument to calculate n!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.factorials):
			return self.factorials[n]
		nextArr = [0] * (n + 1 - len(self.factorials))
		initialI = len(self.factorials)
		prev = self.factorials[-1]
		m = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * i % m
		self.factorials += nextArr
		return self.factorials[n]

	def inv(self, n):
		if n <= -1:
			print('Invalid argument to calculate n^(-1)')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		p = self.MOD
		pi = n % p
		if pi < len(self.invModulos):
			return self.invModulos[pi]
		nextArr = [0] * (n + 1 - len(self.invModulos))
		initialI = len(self.invModulos)
		for i in range(initialI, min(p, n + 1)):
			next = -self.invModulos[p % i] * (p // i) % p
			self.invModulos.append(next)
		return self.invModulos[pi]

	def invFactorial(self, n):
		if n <= -1:
			print('Invalid argument to calculate (n^(-1))!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.invFactorial_):
			return self.invFactorial_[n]
		self.inv(n)
		nextArr = [0] * (n + 1 - len(self.invFactorial_))
		initialI = len(self.invFactorial_)
		prev = self.invFactorial_[-1]
		p = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * self.invModulos[i % p] % p
		self.invFactorial_ += nextArr
		return self.invFactorial_[n]

class Combination:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorial = Factorial(MOD)

	def ncr(self, n, k):
		if k < 0 or n < k:
			return 0
		k = min(k, n - k)
		f = self.factorial
		return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD
mod = 10 ** 9 + 7
omod = 998244353
prime = [True for i in range(10001)]
prime[0] = prime[1] = False

def SieveOfEratosthenes(n=10000):
	p = 2
	c = 0
	while p <= n:
		if prime[p] == True:
			c += 1
			for i in range(p * p, n + 1, p):
				prime[i] = False
		p += 1

class DSU:

	def __init__(self, R, C):
		self.par = range(R * C + 1)
		self.rnk = [0] * (R * C + 1)
		self.sz = [1] * (R * C + 1)

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return
		if self.rnk[xr] < self.rnk[yr]:
			(xr, yr) = (yr, xr)
		if self.rnk[xr] == self.rnk[yr]:
			self.rnk[xr] += 1
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]

	def size(self, x):
		return self.sz[self.find(x)]

	def top(self):
		return self.size(len(self.sz) - 1) - 1

class LazySegTree:

	def __init__(self, _op, _e, _mapping, _composition, _id, v):

		def set(p, x):
			assert 0 <= p < _n
			p += _size
			for i in range(_log, 0, -1):
				_push(p >> i)
			_d[p] = x
			for i in range(1, _log + 1):
				_update(p >> i)

		def get(p):
			assert 0 <= p < _n
			p += _size
			for i in range(_log, 0, -1):
				_push(p >> i)
			return _d[p]

		def prod(l, r):
			assert 0 <= l <= r <= _n
			if l == r:
				return _e
			l += _size
			r += _size
			for i in range(_log, 0, -1):
				if l >> i << i != l:
					_push(l >> i)
				if r >> i << i != r:
					_push(r >> i)
			sml = _e
			smr = _e
			while l < r:
				if l & 1:
					sml = _op(sml, _d[l])
					l += 1
				if r & 1:
					r -= 1
					smr = _op(_d[r], smr)
				l >>= 1
				r >>= 1
			return _op(sml, smr)

		def apply(l, r, f):
			assert 0 <= l <= r <= _n
			if l == r:
				return
			l += _size
			r += _size
			for i in range(_log, 0, -1):
				if l >> i << i != l:
					_push(l >> i)
				if r >> i << i != r:
					_push(r - 1 >> i)
			l2 = l
			r2 = r
			while l < r:
				if l & 1:
					_all_apply(l, f)
					l += 1
				if r & 1:
					r -= 1
					_all_apply(r, f)
				l >>= 1
				r >>= 1
			l = l2
			r = r2
			for i in range(1, _log + 1):
				if l >> i << i != l:
					_update(l >> i)
				if r >> i << i != r:
					_update(r - 1 >> i)

		def _update(k):
			_d[k] = _op(_d[2 * k], _d[2 * k + 1])

		def _all_apply(k, f):
			_d[k] = _mapping(f, _d[k])
			if k < _size:
				_lz[k] = _composition(f, _lz[k])

		def _push(k):
			_all_apply(2 * k, _lz[k])
			_all_apply(2 * k + 1, _lz[k])
			_lz[k] = _id
		_n = len(v)
		_log = _n.bit_length()
		_size = 1 << _log
		_d = [_e] * (2 * _size)
		_lz = [_id] * _size
		for i in range(_n):
			_d[_size + i] = v[i]
		for i in range(_size - 1, 0, -1):
			_update(i)
		self.set = set
		self.get = get
		self.prod = prod
		self.apply = apply
MIL = 1 << 20

def makeNode(total, count):
	return total * MIL + count

def getTotal(node):
	return math.floor(node / MIL)

def getCount(node):
	return node - getTotal(node) * MIL
nodeIdentity = makeNode(0.0, 0.0)

def nodeOp(node1, node2):
	return node1 + node2
	return makeNode(getTotal(node1) + getTotal(node2), getCount(node1) + getCount(node2))
identityMapping = -1

def mapping(tag, node):
	if tag == identityMapping:
		return node
	count = getCount(node)
	return makeNode(tag * count, count)

def composition(mapping1, mapping2):
	return mapping1 if mapping1 != identityMapping else mapping2

class LazySegUpdate:

	def __init__(self, N):
		self.N = N
		n = 4 * N
		self.tree = [0] * n
		self.lazy = [0] * n

	def queryHelper(self, index, s, e, l, r):
		if self.lazy[index]:
			update = self.lazy[index]
			self.lazy[index] = 0
			self.tree[index] = max(self.tree[index], update)
			if s != e:
				self.lazy[2 * index] = max(self.lazy[2 * index], update)
				self.lazy[2 * index + 1] = max(self.lazy[2 * index + 1], update)
		if s > e or s > r or e < l:
			return 0
		if s >= l and e <= r:
			return self.tree[index]
		mid = (s + e) // 2
		return max(self.queryHelper(2 * index, s, mid, l, r), self.queryHelper(2 * index + 1, mid + 1, e, l, r))

	def updateHelper(self, index, s, e, l, r, h):
		if self.lazy[index]:
			update = self.lazy[index]
			self.lazy[index] = 0
			self.tree[index] = max(self.tree[index], update)
			if s != e:
				self.lazy[2 * index] = max(self.lazy[2 * index], update)
				self.lazy[2 * index + 1] = max(self.lazy[2 * index + 1], update)
		if s > e or s > r or e < l:
			return
		if s >= l and e <= r:
			self.tree[index] = max(self.tree[index], h)
			if s != e:
				self.lazy[2 * index] = max(self.lazy[2 * index], h)
				self.lazy[2 * index + 1] = max(self.lazy[2 * index + 1], h)
			return
		mid = (s + e) // 2
		self.updateHelper(2 * index, s, mid, l, r, h)
		self.updateHelper(2 * index + 1, mid + 1, e, l, r, h)
		self.tree[index] = max(self.tree[2 * index], self.tree[2 * index + 1])

	def query(self, l, r):
		return self.queryHelper(1, 0, self.N - 1, l, r - 1)

	def update(self, l, r, h):
		self.updateHelper(1, 0, self.N - 1, l, r - 1, h)

def memodict(f):

	class memodict(dict):

		def __missing__(self, key):
			ret = self[key] = f(key)
			return ret
	return memodict().__getitem__

def pollard_rho(n):
	if n & 1 == 0:
		return 2
	if n % 3 == 0:
		return 3
	s = (n - 1 & 1 - n).bit_length() - 1
	d = n >> s
	for a in [2, 325, 9375, 28178, 450775, 9780504, 1795265022]:
		p = pow(a, d, n)
		if p == 1 or p == n - 1 or a % n == 0:
			continue
		for _ in range(s):
			prev = p
			p = p * p % n
			if p == 1:
				return math.gcd(prev - 1, n)
			if p == n - 1:
				break
		else:
			for i in range(2, n):
				(x, y) = (i, (i * i + 1) % n)
				f = math.gcd(abs(x - y), n)
				while f == 1:
					(x, y) = ((x * x + 1) % n, (y * y + 1) % n)
					y = (y * y + 1) % n
					f = math.gcd(abs(x - y), n)
				if f != n:
					return f
	return n

@memodict
def prime_factors(n):
	if n <= 1:
		return Counter()
	f = pollard_rho(n)
	return Counter([n]) if f == n else prime_factors(f) + prime_factors(n // f)

def distinct_factors(n):
	factors = [1]
	for (p, exp) in prime_factors(n).items():
		factors += [p ** i * factor for factor in factors for i in range(1, exp + 1)]
	return factors

def all_factors(n):
	(small, large) = ([], [])
	for i in range(1, int(n ** 0.5) + 1, 2 if n & 1 else 1):
		if not n % i:
			small.append(i)
			large.append(n // i)
	if small[-1] == large[-1]:
		large.pop()
	large.reverse()
	small.extend(large)
	return small

class SortedList:

	def __init__(self, iterable=[], _load=200):
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))

def binarySearch(arr, n, key):
	left = 0
	right = n - 1
	mid = 0
	res = n
	while left <= right:
		mid = (right + left) // 2
		if arr[mid] >= key:
			res = mid
			right = mid - 1
		else:
			left = mid + 1
	return res

def binarySearch1(arr, n, key):
	left = 0
	right = n - 1
	mid = 0
	res = -1
	while left <= right:
		mid = (right + left) // 2
		if arr[mid] > key:
			right = mid - 1
		else:
			res = mid
			left = mid + 1
	return res
tt = 1
tt = int(input())
for _ in range(tt):
	(n, k, x) = map(int, input().split())
	s = input()
	t = []
	if k == 0:
		ans = []
		for i in s:
			if i == 'a':
				ans.append(i)
		print(*ans, sep='')
		continue
	c = 0
	ast = []
	for i in range(n):
		if s[i] == '*':
			c += 1
		if s[i] == 'a' or i == n - 1:
			if c:
				ast.append(k * c + 1)
				t.append('*')
			if s[i] == 'a':
				t.append('a')
			c = 0
	m = len(ast)
	suf = [1] * m
	for i in range(m - 2, -1, -1):
		suf[i] = suf[i + 1] * ast[i + 1]
		suf[i] = min(suf[i], 10 ** 19)
	b = []
	x -= 1
	for i in range(m):
		md = x % suf[i]
		ct = x // suf[i]
		b.append(ct)
		x = md
	ans = []
	j = 0
	for i in range(len(t)):
		if t[i] == 'a':
			ans.append(t[i])
		else:
			for l in range(b[j]):
				ans.append('b')
			j += 1
	print(*ans, sep='')


from sys import stdin

def read_input():
	(n, k, x) = map(int, stdin.readline().split())
	s = stdin.readline().rstrip()
	return (n, k, x, s)

def solve(n, k, x, s):
	a = [len(si) * k for si in s.split('a') if si != '']
	na = [len(si) for si in s.split('*') if si != '']
	nb = []
	p = 1
	for i in range(len(a) - 1, -1, -1):
		p *= a[i] + 1
		if x <= p:
			x -= 1
			while p > 1:
				p //= a[i] + 1
				nb.append(x // p)
				x %= p
				i += 1
			break
	answer = []
	if s[-1] == 'a':
		for (nai, nbi) in zip(na[::-1], nb[::-1]):
			answer.append(nai * 'a')
			answer.append(nbi * 'b')
		if len(na) > len(nb):
			for nai in na[len(na) - len(nb) - 1::-1]:
				answer.append(nai * 'a')
	else:
		for (nai, nbi) in zip(na[::-1], nb[::-1]):
			answer.append(nbi * 'b')
			answer.append(nai * 'a')
		if len(na) < len(nb):
			answer.append(nb[0] * 'b')
		elif len(na) > len(nb):
			for nai in na[len(na) - len(nb) - 1::-1]:
				answer.append(nai * 'a')
	answer = ''.join(answer[::-1])
	if answer == '':
		answer = 'b'
	return answer

def main():
	t = int(stdin.readline())
	for _ in range(t):
		input = read_input()
		answer = solve(*input)
		print(answer)
main()


from __future__ import division, print_function
import math
import sys
import os
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def inp():
	return int(input())

def inps():
	return input().strip()

def inlt():
	return list(map(int, input().split()))

def insr():
	s = input().strip()
	return list(s[:len(s)])

def invr():
	return map(int, input().split())
for _ in range(inp()):
	(a, b, c) = invr()
	l = insr()
	n = len(l)
	v = []
	i = 0
	strt = 0
	while i < n:
		if l[i] == 'a':
			if strt > 0:
				v.append(strt * b + 1)
				strt = 0
			v.append('a')
		else:
			strt += 1
		i += 1
	if strt > 0:
		v.append(strt * b + 1)
		strt = 0
	i = len(v) - 1
	tx = c
	st = ''
	cnt = []
	while tx and i > -1:
		if v[i] != 'a':
			if tx % v[i] == 0:
				temp = [tx // v[i], v[i]]
			else:
				temp = [tx // v[i], tx % v[i]]
			if tx % v[i] == 0:
				tx = tx // v[i]
			else:
				tx = tx // v[i] + 1
			v[i] = temp
		i -= 1
	int_count = 0
	i = len(v) - 1
	while i > -1:
		if v[i] == 'a':
			st += 'a'
		else:
			(a, b) = v[i]
			st += 'b' * (b - 1)
		i -= 1
	st = st[::-1]
	print(st)


import sys
import re
import math
from math import log2 as lg
from collections import deque
import random
import heapq
import itertools
const = 1000000007
ep = 1e-08
n = int(input())
for i in range(n):
	line = list(map(int, input().split()))
	(n, k, x) = (line[0], line[1], line[2] - 1)
	curr = input()
	chunks = []
	index = 0
	while index < len(curr):
		now = curr[index]
		temp = 0
		while index < len(curr) and curr[index] == now:
			temp += 1
			index += 1
		if now == 'a':
			chunks.append(['a', temp])
		else:
			chunks.append(['*', temp * k + 1])
	index = len(chunks) - 1
	while index >= 0 and x > 0:
		if chunks[index][0] == 'a':
			index -= 1
			continue
		howmany = x % chunks[index][1]
		x //= chunks[index][1]
		chunks[index][0] = 'b'
		chunks[index][1] = howmany
		index -= 1
	ans = []
	for term in chunks:
		if term[0] == '*':
			continue
		elif term[0] == 'a':
			ans.append('a' * term[1])
		else:
			ans.append('b' * term[1])
	print(''.join(ans))


from sys import stdin
input = stdin.readline
from math import ceil

def get(x):
	x_dup = x
	value = 1
	for i in range(len(take) - 1, -1, -1):
		if x <= value * (take[i] - (i != len(take) - 1)):
			this = ceil(x / value)
			vals[i] = this - (i == len(take) - 1)
			x_dup = x_dup - this * value
			break
		x -= value * (take[i] - (i != len(take) - 1))
		value *= take[i]
	return x_dup

def answer(x):
	global vals
	if len(take) == 0:
		return a
	while x:
		x = get(x)
	(ans, i, ind) = ('', 0, 0)
	while i < n:
		if a[i] == 'a':
			ans += 'a'
			i += 1
		else:
			ans += 'b' * vals[ind]
			while i < n and a[i] == '*':
				i += 1
			ind += 1
	return ans
for T in range(int(input())):
	(n, k, x) = map(int, input().split())
	a = input().strip()
	(take, count) = ([], 0)
	for i in range(n):
		if a[i] == '*':
			count += 1
		else:
			if count:
				take.append(count * k + 1)
			count = 0
	if count:
		take.append(count * k + 1)
	vals = [0] * len(take)
	print(answer(x))


import sys
from random import randint
input = lambda : sys.stdin.readline().strip()
intput = lambda : map(int, input().split())

def toStr(new, res):
	a = []
	n = len(new)
	c = 0
	for i in range(n):
		if new[i] == 'a':
			a.append('a')
		else:
			a.append('b' * res[c])
			c += 1
	return ''.join(a)

def solve(k, x, s):
	s += '$'
	stk = 0
	new = []
	for (i, ch) in enumerate(s):
		if ch == '*':
			stk += 1
		elif i != 0 and s[i - 1] != 'a':
			new.append(stk)
			stk = 0
		if ch == 'a':
			new.append('a')
	q = [y for y in new if y != 'a']
	if not q:
		return s[:-1]
	n = len(q)
	for i in range(n):
		q[i] = q[i] * k + 1
	for i in range(n - 2, -1, -1):
		q[i] *= q[i + 1]
	x -= 1
	for i in range(n - 1, -1, -1):
		if q[i] > x:
			break
	res = [0] * n
	if i == n - 1:
		res[i] = x
		return toStr(new, res)
	while i < n - 1:
		b = x // q[i + 1]
		x %= q[i + 1]
		res[i] = b
		i += 1
	res[-1] = x
	return toStr(new, res)

def random():
	b = []
	for i in range(randint(0, 50)):
		a = randint(0, 1)
		x = randint(0, 20)
		if a == 0:
			b.append(x * '*')
		else:
			b.append(x * 'a')
	return ''.join(b)

def test(x, k, s):
	A = set()

	def dfs(i, curr):
		if i >= len(s):
			A.add(str(curr))
			return
		if s[i] == '*':
			for j in range(k + 1):
				q = curr + 'b' * j
				dfs(i + 1, q)
		else:
			dfs(i + 1, curr + 'a')
	dfs(0, '')
	return sorted(A)[x - 1]
(T,) = intput()
for _ in range(T):
	(n, k, x) = intput()
	s = input()
	print(solve(k, x, s))


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	st = input()[:-1]
	star = []
	precount = 0
	isStar = False
	for i in range(n):
		if st[i] == '*':
			precount += 1
			isStar = True
		elif isStar:
			star.append(precount * k + 1)
			isStar = False
			precount = 0
	if isStar:
		star.append(precount * k + 1)
	le = len(star)
	mul = [1] * (le + 1)
	for i in range(le - 1, -1, -1):
		mul[i] = mul[i + 1] * star[i]
	req = False
	for i in range(le):
		if not req:
			if mul[i] >= x and mul[i + 1] < x:
				req = True
			else:
				mul[i] = 0
		if req:
			quo = x // mul[i + 1]
			quo -= not bool(x % mul[i + 1])
			mul[i] = quo
			x -= quo * mul[i + 1]
	final_ans = ''
	ind = 0
	isStar = False
	for i in range(n):
		if st[i] == '*':
			if not isStar:
				isStar = True
				final_ans += 'b' * mul[ind]
				ind += 1
		else:
			final_ans += 'a'
			isStar = False
	print(final_ans)


import sys
input = sys.stdin.readline

def inp():
	return int(input())

def st():
	return input().rstrip('\n')

def lis():
	return list(map(int, input().split()))

def ma():
	return map(int, input().split())
t = inp()
while t:
	t -= 1
	(n, k, x) = ma()
	s = st()
	if x == 1:
		for i in s:
			if i != '*':
				print(i, end='')
		print()
		continue
	s = s[::-1]
	sofar = 1
	s = list(s)
	ast = 0
	s1 = []
	co = 0
	for i in range(n):
		if s[i] == 'a':
			if ast:
				s1.append(ast * k + 1)
			s1.append('a')
			ast = 0
		else:
			ast += 1
	if ast:
		s1.append(ast * k + 1)
	res = ''
	fl = 0
	for i in range(len(s1)):
		if fl:
			if s1[i] == 'a':
				continue
			else:
				s1[i] = 0
		if s1[i] == 'a':
			continue
		elif sofar * s1[i] < x:
			sofar *= s1[i]
		else:
			fl = 1
			for j in range(i, -1, -1):
				if s1[j] == 'a':
					continue
				if j != i:
					sofar = sofar // s1[j]
				for j1 in range(s1[j]):
					if (j1 + 1) * sofar < x:
						continue
					s1[j] = j1
					x -= j1 * sofar
					break
	for i in s1:
		if i == 'a':
			res += 'a'
		else:
			res += 'b' * i
	print(res[::-1])


for _ in range(int(input())):
	(N, K, X) = map(int, input().split())
	X -= 1
	dat = input()
	amt = dat.split('a')[::-1]
	ast = len(amt) - amt.count('')
	much = []
	for c in amt:
		if len(c) == 0:
			continue
		much.append(X % (K * len(c) + 1))
		X //= K * len(c) + 1
	much += [0] * (ast - len(much))
	much = much[::-1]
	i = 0
	j = 0
	while i < len(dat):
		if dat[i] == 'a':
			print('a', end='')
			i += 1
		else:
			print('b' * much[j], end='')
			j += 1
			while i < len(dat) and dat[i] == '*':
				i += 1
	print()


from bisect import bisect_left, bisect_right
import math
for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	if x == 1 or s.count('*') == 0:
		print('a' * s.count('a'))
		continue
	a = [1]
	pos = []
	last = n - 1
	while last >= 0 and s[last] == 'a':
		last -= 1
	c = 0
	while last >= 0 and s[last] == '*':
		last -= 1
		c += 1
	a.append(c * k + 1)
	if c != 0:
		pos.append([last + 1, c * k])
	while last >= 0:
		while last >= 0 and s[last] == 'a':
			last -= 1
		c = 0
		if last < 0:
			break
		while last >= 0 and s[last] == '*':
			c += 1
			last -= 1
		a.append(a[-1] * (k * c + 1))
		pos.append([last + 1, k * c])
	ind = bisect_left(a, x)
	p = a[ind - 1]
	d = math.ceil(x / p)
	left = d * p - x
	pos[ind - 1][1] = d - 1
	for i in range(ind - 2, -1, -1):
		if left >= a[i + 1] - a[i]:
			pos[i][1] = 0
			left -= a[i + 1] - a[i]
		else:
			j = left // a[i]
			if j == 0 and i == 0:
				pos[i][1] -= left
				left = 0
			else:
				left %= a[i]
				pos[i][1] -= j
		if left == 0:
			break
	i = 0
	ans = ''
	last = len(pos)
	while i < n:
		while i < n and s[i] == 'a':
			ans += 'a'
			i += 1
		if i >= n:
			break
		while i < n and s[i] == '*':
			i += 1
		last -= 1
		if last < ind:
			ans += 'b' * pos[last][1]
	print(ans)


t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	(np, kp, xp) = (n, k, x)
	s = list(input())
	arr = []
	i = 0
	sp = s[:]
	if x == 1:
		s = ''.join(s)
		s = s.replace('*', '')
		print(s)
		continue
	x -= 1
	while i < len(s):
		if s[i] != '*':
			arr += [s[i]]
			i += 1
		else:
			count = 1
			while i < len(s) and s[i] == '*':
				i += 1
				count += 1
			arr += [(count - 1) * k]
	i = len(arr) - 1
	remaining = x
	while i >= 0:
		if arr[i] == 'a':
			i -= 1
			continue
		nn = arr[i]
		kk = remaining % (nn + 1)
		arr[i] = 'b' * int(kk)
		remaining = remaining // (nn + 1)
		if remaining == 0:
			break
		i -= 1
	arr = [item for item in arr if not isinstance(item, int)]
	print(''.join(arr))


import sys
import os.path
if os.path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')
	sys.stderr = open('error.txt', 'w')
depth = 200001
mod = 1000000007
lim = mod * mod
sys.setrecursionlimit(depth)
linp = lambda : list(minp())
minp = lambda : map(int, input().split())
from math import inf, ceil, sqrt, log2, gcd
from collections import defaultdict, deque
dxy = [(1, 0), (-1, 0), (0, 1), (0, -1)]

def expo(a, b):
	if not b:
		return 1
	v = expo(a, b // 2)
	v = v * v % mod
	if b % 2:
		v = v * a % mod
	return v

def modinv(a, b):
	d = expo(b, mod - 2)
	v = a * d % mod
	return v

def checkPrime(n):
	if n < 4:
		return True
	if n % 2 == 0:
		return False
	for i in range(3, int(sqrt(n)) + 1, 2):
		if n % i == 0:
			return False
	return True

def highestPowerof2(x):
	x |= x >> 1
	x |= x >> 2
	x |= x >> 4
	x |= x >> 8
	x |= x >> 16
	return x ^ x >> 1

def isVowel(char):
	return char.lower() in 'aeiou'
for _ in range(int(input())):
	(n, k, x) = minp()
	s = str(input())
	(a, c) = (list(), 0)
	x = x - 1
	for e in s:
		if e == '*':
			c = c + 1
		else:
			if c > 0:
				a.append(c)
			c = 0
	if c > 0:
		a.append(c)
	m = len(a)
	for i in range(m):
		a[i] = a[i] * k + 1
	b = [a[i] for i in range(m)]
	for i in range(m - 2, -1, -1):
		b[i] = b[i] * b[i + 1]
	b.append(1)
	c = list()
	for i in range(m):
		v = x // b[i + 1]
		c.append(v)
		x = x - v * b[i + 1]
	(r, f, i) = ([], True, 0)
	for e in s:
		if e == '*':
			f = False
		else:
			if not f:
				r.append('b' * c[i])
				i = i + 1
				f = True
			r.append(e)
	if not f:
		r.append('b' * c[i])
	print(''.join(r))


for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	seg = []
	temp = 0
	for i in range(n):
		if s[i] == 'a' and temp > 0:
			seg += [temp * k + 1]
			temp = 0
		elif s[i] == '*':
			temp += 1
	if temp > 0:
		seg += [temp * k + 1]
	ans = []
	x -= 1
	for i in range(len(seg) - 1, -1, -1):
		ans += [x % seg[i]]
		x //= seg[i]
		if x == 0:
			break
	if len(ans) < len(seg):
		ans += [0] * (len(seg) - len(ans))
	j = len(ans) - 1
	for i in range(n):
		if s[i] == 'a':
			print('a', end='')
		elif i < n - 1 and s[i] == '*' and (s[i + 1] == 'a'):
			print('b' * ans[j], end='')
			j -= 1
	if j == 0:
		print('b' * ans[0], end='')
	print()


def solver():
	n_1 = int(input())
	for _ in range(n_1):
		(n, k, x) = map(int, input().split())
		f = input()
		a = list(filter(lambda y: y != '', f.split('a')))
		list_of_cases = []
		tmp = ''
		for i in f:
			if i == 'a':
				list_of_cases.append(tmp)
				tmp = ''
				list_of_cases.append('a')
			else:
				tmp = tmp + '*'
		list_of_cases.append(tmp)
		list_of_cases = list(filter(lambda y: y != '', list_of_cases))
		n_of_cases = 1
		for multiplier in a:
			n_of_cases = n_of_cases * (len(multiplier) * k + 1)
		final = ''
		for i in list_of_cases:
			if i == 'a':
				final = final + 'a'
			else:
				length = len(i)
				chunks = length * k + 1
				n_of_cases = n_of_cases // chunks
				for j in range(chunks):
					if j * n_of_cases < x <= (j + 1) * n_of_cases:
						final = final + j * 'b'
						x = x % n_of_cases
						if x == 0:
							x = n_of_cases
		print(final)
solver()


t = int(input())
for x in range(t):
	[n, k, x] = [int(i) for i in input().split()]
	x -= 1
	s = input()
	s = s[::-1]
	ans = ''
	(idx, cnt, cur) = (0, 0, 1)
	while idx < len(s):
		if s[idx] != '*':
			ans += s[idx]
			idx += 1
		else:
			while idx < len(s) and s[idx] == '*':
				cnt += 1
				idx += 1
			cur = cnt * k + 1
			ans += 'b' * (x % cur)
			x //= cur
			cnt = 0
	print(ans[::-1])


import sys
import bisect
import math
from collections import deque
input = lambda : sys.stdin.readline().strip()
mod = 10 ** 9 + 7

def solve():
	(n, k, x) = map(int, input().split())
	s = input()
	a = []
	for i in range(n):
		if s[i] == 'a':
			a.append(s[i])
		elif i > 0 and s[i - 1] != 'a':
			a[-1] += k
		else:
			a.append(k)
	(r, j) = (1, 0)
	n = len(a)
	for i in reversed(range(n)):
		if a[i] != 'a':
			r *= a[i] + 1
			if r >= x:
				j = i
				break
	x -= 1
	new_s = ''
	for i in range(j):
		if a[i] == 'a':
			new_s += 'a'
	for i in range(j, n):
		if a[i] == 'a':
			new_s += 'a'
		else:
			r = r // (a[i] + 1)
			r1 = min(x // r, a[i])
			new_s += 'b' * r1
			x = x - r1 * r
	return new_s
t = 1
t = int(input())
for _ in range(t):
	print(solve())


import sys
input = sys.stdin.readline

def solve():
	(n, k, x) = map(int, input().split())
	s = list(input().strip())
	arr = []
	curr = 0
	for i in range(n):
		if s[i] == 'a':
			if curr:
				arr.append((i - 1, curr * k + 1))
				curr = 0
		else:
			curr += 1
	if curr:
		arr.append((n - 1, curr * k + 1))
	x -= 1
	while x > 0 and arr:
		(idx, d) = arr.pop()
		s[idx] = x % d * 'b'
		x //= d
	ans = []
	for c in s:
		if c != '*':
			ans.append(c)
	return ''.join(ans)
for _ in range(int(input())):
	print(solve())


t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	s = str(input())
	s = ''.join(list(reversed(s)))
	ans = ''
	cnt = 0
	num = x - 1
	for i in range(n):
		if s[i] == 'a':
			if cnt > 0:
				tmp = num % (cnt * k + 1)
				for j in range(tmp):
					ans += 'b'
				num //= cnt * k + 1
			cnt = 0
			ans += 'a'
		else:
			cnt += 1
	if cnt > 0:
		tmp = num % (cnt * k + 1)
		for j in range(tmp):
			ans += 'b'
	print(''.join(list(reversed(ans))))


import sys
import io, os
input = sys.stdin.readline

def rl(s):
	if not s:
		return []
	cur = s[0]
	cnt = 0
	res = []
	for c in s:
		if c == cur:
			cnt += 1
		else:
			res.append((cnt, cur))
			cur = c
			cnt = 1
	else:
		res.append((cnt, cur))
	return res
t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	x -= 1
	s = str(input().rstrip())
	nx = [n] * (n + 1)
	for i in reversed(range(n)):
		c = s[i]
		if c == 'a':
			nx[i] = i
		else:
			nx[i] = nx[i + 1]
	tot = 0
	ans = []
	RL = rl(s)
	M = 1
	for (i, (cnt, cur)) in enumerate(RL):
		if cur == '*':
			M *= cnt * k + 1
	for (i, (cnt, cur)) in enumerate(RL):
		if cur == 'a':
			ans += ['a'] * cnt
		else:
			M //= cnt * k + 1
			(q, x) = divmod(x, M)
			ans += ['b'] * q
	if x:
		ans += ['b'] * x
	print(''.join(ans))


for ___ in range(int(input())):
	(n, k, x) = list(map(int, input().split()))
	s = input()
	x -= 1
	sSplit = []
	for c in s:
		if c == 'a':
			sSplit.append(c)
		elif len(sSplit) > 0 and sSplit[-1] != 'a':
			sSplit[-1] += 1
		else:
			sSplit.append(1)
	for i in range(len(sSplit)):
		if sSplit[i] != 'a':
			sSplit[i] = sSplit[i] * k + 1
	resultList = ['' for _ in range(len(sSplit))]
	for i in reversed(range(len(resultList))):
		if sSplit[i] == 'a':
			resultList[i] = 'a'
			continue
		if x == 0:
			continue
		resultList[i] = 'b' * (x % sSplit[i])
		x //= sSplit[i]
	print(''.join(resultList))


import bisect
import collections
import copy
import enum
import functools
import heapq
import itertools
import math
import random
import re
import sys
import time
import string
from typing import List
t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	x -= 1
	p = []
	s = input()
	for (i, c) in enumerate(s):
		if c == 'a':
			p.append(['a', 1])
		elif not p or p[-1][0] == 'a':
			p.append(['b', k + 1])
		else:
			p[-1][1] += k
	p.append(['a', 1])
	for i in range(len(p) - 2, -1, -1):
		if p[i + 1][1] > x:
			p[i][1] = p[i + 1][1]
		else:
			p[i][1] *= p[i + 1][1]
	ans = ''
	for i in range(len(p) - 1):
		if p[i][0] == 'a':
			ans += 'a'
		elif p[i + 1][1] > x:
			continue
		else:
			ans += 'b' * (x // p[i + 1][1])
			x %= p[i + 1][1]
	print(ans)


from sys import stdin, stdout
rd = lambda : list(map(int, stdin.readline().split()))
rds = lambda : stdin.readline().rstrip()
ii = lambda : int(stdin.readline())
INF = 1 << 62
mod = 10 ** 9 + 7

def solve(s, k, x):
	s = s[::-1]
	x -= 1
	res = []
	bs = []
	i = 0
	while i < len(s):
		if s[i] == 'a':
			res.append('a')
			i += 1
		else:
			curr = 0
			while i < len(s) and s[i] != 'a':
				i += 1
				curr += 1
			bs.append((len(res), curr * k))
			res.append('_')
	for (j, lim) in bs:
		d = x % (lim + 1)
		x //= lim + 1
		res[j] = 'b' * d
	return ''.join(res)[::-1]
for _ in range(ii()):
	(n, k, x) = rd()
	s = rds()
	print(solve(s, k, x))


from collections import defaultdict as dd
import math
import sys
input = sys.stdin.readline

def nn():
	return int(input())

def li():
	return list(input())

def mi():
	return map(int, input().split())

def lm():
	return list(map(int, input().split()))

def solve():
	(n, k, x) = mi()
	s = input()
	blens = []
	count = 0
	for i in range(len(s) - 1):
		if s[i] == '*':
			count += 1
		if s[i] == 'a' and count > 0:
			blens.append(count)
			count = 0
	if count > 0:
		blens.append(count)
	if len(blens) == 0:
		print(s[:-1])
		return
	bplace = -1
	count = 0
	bcounts = [0 for i in range(len(blens))]
	bcounts[-1] = blens[-1] * k + 1
	for i in range(1, len(blens)):
		bcounts[-i - 1] = bcounts[-i] * (k * blens[-i - 1] + 1)
	bans = [0 for i in range(len(blens))]
	x -= 1
	for i in range(1, len(blens)):
		bans[i - 1] = x // bcounts[i]
		x = x % bcounts[i]
	bans[-1] = x
	out = []
	count = 0
	place = 0
	for i in range(len(s) - 1):
		if s[i] == 'a':
			out.append('a')
			count = 0
		if s[i] == '*' and count == 0:
			count += 1
			out.append('b' * bans[place])
			place += 1
	print(''.join(out))
q = nn()
for _ in range(q):
	solve()


t = int(input())

def get_variable_base(n, digit_value):
	current_digit = 0
	suffix_product = get_suffix_product(digit_value)
	based = []
	while current_digit < len(digit_value):
		based.append(n // suffix_product[current_digit + 1])
		n -= suffix_product[current_digit + 1] * based[-1]
		current_digit += 1
	return based

def get_suffix_product(digit_values):
	suffix_product = [1] * (len(digit_values) + 1)
	for i in range(len(suffix_product) - 2, -1, -1):
		suffix_product[i] = suffix_product[i + 1] * digit_values[i]
	return suffix_product

def solve():
	(n, k, x) = map(int, input().split())
	s = input()
	starstrings = list(filter(lambda x: len(x) > 0, s.split('a')))
	astrings = list(filter(lambda x: len(x) > 0, s.split('*')))
	digit_values = list(map(lambda x: len(x) * k + 1, starstrings))
	b_cnt = get_variable_base(x - 1, digit_values)
	b_ptr = 0
	res = ''
	if s[0] == '*':
		res += 'b' * b_cnt[0]
		b_ptr = 1
	for astring in astrings:
		res += astring
		if b_ptr < len(b_cnt):
			res += 'b' * b_cnt[b_ptr]
		b_ptr += 1
	print(res)
for i in range(t):
	solve()


import sys
IN = sys.stdin
OUT = sys.stdout
tc = int(IN.readline())
for ti in range(tc):
	(n, k, x) = map(int, IN.readline().strip().split())
	x -= 1
	s = IN.readline().strip()
	a = list()
	b = list()
	d = list()
	a.append('')
	for c in s:
		if c == 'a':
			if len(a) > len(b):
				a[-1] += 'a'
			else:
				a.append('a')
		elif len(a) > len(b):
			b.append(k + 1)
		else:
			b[-1] += k
	b.reverse()
	for bb in b:
		d.append('b' * (x % bb))
		x = x // bb
	d.reverse()
	for i in range(len(d)):
		print(a[i], d[i], end='', sep='')
	if len(a) > len(b):
		print(a[len(d)], end='', sep='')
	print()


for _ in range(int(input())):
	(a, b, c) = map(int, input().split())
	c -= 1
	s = input()[::-1]
	res = []
	i = 0
	while i < a:
		if s[i] == 'a':
			res.append(s[i])
		else:
			j = i
			while j + 1 < a and s[j + 1] == s[i]:
				j += 1
			cur = (j - i + 1) * b + 1
			res.append('b' * (c % cur))
			c //= cur
			i = j
		i += 1
	print(''.join(res[::-1]))


from math import ceil
t = int(input())
for _ in range(t):
	(n, k, x) = list(map(int, input().split()))
	s = input()
	if k == 0:
		print(s.replace('*', ''))
		continue
	cnt = 0
	lst = []
	for c in s:
		if c == 'a':
			if cnt:
				lst.append(cnt * k)
			lst.append('a')
			cnt = 0
		else:
			cnt += 1
	else:
		if cnt:
			lst.append(cnt * k)
	cnt = 1
	l = len(lst)
	flg = False
	for i in range(l - 1, -1, -1):
		if lst[i] == 'a':
			continue
		if flg:
			lst[i] = 0
			continue
		cnt *= lst[i] + 1
		if cnt >= x:
			for j in range(i, l):
				if lst[j] == 'a':
					continue
				if x:
					cnt //= lst[j] + 1
					lst[j] = ceil(x / cnt) - 1
					x -= cnt * lst[j]
			flg = True
	for i in range(l):
		if lst[i] == 'a':
			continue
		lst[i] = 'b' * lst[i]
	print(''.join(lst))


import sys
t = int(sys.stdin.readline())
for _ in range(t):
	(n, k, x) = map(int, sys.stdin.readline().split())
	s = input()
	arr = []
	for c in s:
		if not arr or arr[-1][0] != c:
			arr.append([c, 1])
		else:
			arr[-1][1] += 1
	cnt = []
	tot = 1
	for (a, b) in arr[::-1]:
		if a == '*':
			bk = b * k + 1
			cnt.append((bk, tot))
			tot *= bk
	cnt.reverse()
	x -= 1
	c2 = []
	for (a, b) in cnt:
		c2.append(x // b)
		x %= b
	c2.reverse()
	i = 0
	ans = ''
	for (a, b) in arr:
		if a == '*':
			ans += 'b' * c2.pop()
		else:
			ans += a * b
	print(ans)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	ans = 0
	(n, k, x) = map(int, input().split())
	s = input().rstrip()
	alist = []
	aster = []
	start = s[0]
	if start == 'a':
		alist.append(1)
	else:
		aster.append(1)
	for i in range(1, n):
		if s[i - 1] == s[i]:
			if s[i] == 'a':
				alist[-1] += 1
			else:
				aster[-1] += 1
		elif s[i] == 'a':
			alist.append(1)
		else:
			aster.append(1)
	if len(aster) == 0:
		print(s)
	else:
		for i in range(len(aster)):
			aster[i] *= k
		ans_ast = [0 for _ in range(len(aster))]
		ast_val = [0 for _ in range(len(aster))]
		ast_val[-1] = 1
		for i in range(len(aster) - 2, -1, -1):
			ast_val[i] = ast_val[i + 1] * (aster[i + 1] + 1)
		now = x - 1
		for i in range(len(aster)):
			ans_ast[i] = now // ast_val[i]
			now = now % ast_val[i]
		ans = ''
		if start == 'a':
			for i in range(len(alist)):
				ans += 'a' * alist[i]
				try:
					ans += 'b' * ans_ast[i]
				except:
					pass
		else:
			for i in range(len(aster)):
				ans += 'b' * ans_ast[i]
				try:
					ans += 'a' * alist[i]
				except:
					pass
		print(ans)


from sys import stdin, stdout, setrecursionlimit
from math import gcd, sqrt, factorial, pi, inf
from collections import deque, defaultdict
from bisect import bisect, bisect_left
from time import time
from itertools import permutations as per
from heapq import heapify, heappush, heappop, heappushpop
input = stdin.readline
R = lambda : map(int, input().split())
I = lambda : int(input())
S = lambda : input().rstrip('\r\n')
L = lambda : list(R())
P = lambda x: stdout.write(str(x) + '\n')
lcm = lambda x, y: x * y // gcd(x, y)
nCr = lambda x, y: f[x] * inv(f[y] * f[x - y] % N) % N
inv = lambda x: pow(x, N - 2, N)
sumx = lambda x: (x ** 2 + x) // 2
N = 10 ** 9 + 7
for _ in range(I()):
	(n, k, q) = R()
	s = S()
	a = []
	cnt = []
	p = '#'
	for i in range(n):
		if s[i] == '*':
			if p == '*':
				cnt[-1] += 1
			else:
				a += ('*',)
				cnt += (1,)
		elif p == 'a':
			cnt[-1] += 1
		else:
			a += ('a',)
			cnt += (1,)
		p = s[i]
	v = [0] * len(a)
	p = 1
	sr = 1
	for i in range(len(a) - 1, -1, -1):
		if a[i] == '*':
			v[i] = p
			p = p * k * cnt[i] + sr
			sr = p
	ans = []
	q -= 1
	for i in range(len(a)):
		if a[i] == 'a':
			ans += (a[i] * cnt[i],)
		elif q >= v[i]:
			ans += ('b' * (q // v[i]),)
			q %= v[i]
	print(*ans, sep='')


t = int(input())
for T in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	prev = 1
	ans = ''
	ind = n - 1
	while ind >= 0:
		i = ind
		if s[i] == 'a':
			ans += 'a'
			ind = ind - 1
		else:
			star = 0
			while i >= 0 and s[i] == '*':
				i = i - 1
				star = star + 1
			star = star * k
			curr = prev + prev * star
			add = (x - 1) % curr // prev
			prev = curr
			ans += 'b' * add
			if i < 0:
				break
			if i > 0:
				ind = i
			else:
				ind = ind - 1
	ans = ans[::-1]
	print(ans)


import sys
import math
from collections import deque, Counter
from sys import stdin
int1 = lambda x: int(x) - 1
stinput = lambda : stdin.readline()[:-1]
ii = lambda : int(stinput())
mi = lambda : map(int, stdin.readline().split())
li = lambda : list(mi())
mi1 = lambda : map(int1, stdin.readline().split())
li1 = lambda : list(mi1())
mis = lambda : map(str, stdin.readline().split())
lis = lambda : list(mis())
from collections import defaultdict
import heapq
mod = 10 ** 9 + 7
Mod = 998244353
INF = 10 ** 18
ans = 0
t = ii()
for _ in range(t):
	(a, b, c) = mi()
	s = stinput()
	x = []
	cnt = 0
	ans = []
	if c == 1:
		for i in s:
			if i == 'a':
				ans.append(i)
		print(''.join(ans))
		continue
	for i in s:
		if i == 'a':
			if cnt > 0:
				x.append(cnt + 1)
				ans.append(-1)
			cnt = 0
			ans.append('a')
		else:
			cnt += b
	if cnt > 0:
		ans.append(-1)
		x.append(cnt + 1)
	tmp = 1
	d = 1
	c -= 1
	while c != 0:
		(x[-d], c) = (c % x[-d], c // x[-d])
		d += 1
	for i in range(len(x) - d + 1):
		x[i] = 0
	tmp = 0
	for i in range(len(ans)):
		if ans[i] == -1:
			ans[i] = 'b' * x[tmp]
			tmp += 1
	print(''.join(ans))


t = int(input())
while t:
	(n, k, x) = map(int, input().split())
	s = str(input())
	dp = [0] * (n + 5)
	a = [0] * (n + 5)
	st = [0] * (n + 5)
	ans = [0] * (n + 5)
	cur = 0
	for (i, j) in enumerate(s):
		if j == 'a':
			if i and s[i - 1] != 'a':
				cur += 1
			a[cur] += 1
		if j == '*':
			st[cur] += 1
	cur = 1
	for i in range(n + 2)[::-1]:
		if st[i]:
			dp[i] = cur
			cur = cur * (st[i] * k + 1)
	for i in range(n + 2):
		if dp[i] and dp[i] < x:
			ans[i] = x // dp[i] - (1 if x % dp[i] == 0 else 0)
			x = x % dp[i] if x % dp[i] != 0 else dp[i]
	fa = ['a' * a[0]]
	for i in range(n + 2):
		fa.append('b' * ans[i])
		fa.append('a' * a[i + 1])
	print(''.join(fa))
	t -= 1


def solution(n, k, x, s):
	current_len = 0
	astrics = []
	for c in s:
		if c == '*':
			current_len += 1
		elif c == 'a':
			if current_len != 0:
				astrics.append(current_len)
			current_len = 0
	if current_len != 0:
		astrics.append(current_len)
	astrics = list(map(lambda y: k * y + 1, astrics))
	x -= 1
	result = []
	for num in reversed(astrics):
		m = x % num
		x //= num
		result.append(m)
	answer = ''
	c = s[0]
	if c == 'a':
		answer = 'a'
	for i in range(1, n):
		if s[i] == 'a' and s[i - 1] == '*':
			num = result.pop()
			answer += num * 'b'
		if s[i] == 'a':
			answer += 'a'
	if s[n - 1] == '*':
		num = result.pop()
		answer += num * 'b'
	return answer
t = int(input())
for i in range(t):
	(n, k, x) = list(map(int, input().split()))
	s = input()
	print(solution(n, k, x, s))


for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	t = [1]
	s = input()
	for y in s:
		if y == '*':
			t[-1] += k
		elif t[-1] != 1:
			t.append(1)
	if t[-1] == 1:
		t.pop(-1)
	if x == 1:
		print(s.replace('*', ''))
	else:
		x -= 1
		ans = []
		for c in t[::-1]:
			ans.append(x % c)
			x //= c
		ref = ans[::-1]
		fans = []
		p = False
		c = 0
		for x in s:
			if x == '*':
				if p == False:
					fans.append('b' * ref[c])
					c += 1
					p = True
			else:
				fans.append('a')
				p = False
		print(''.join(fans))


def main(t):
	(n, k, x) = map(int, input().split())
	s = input()
	digits = []
	star = 0
	for i in range(n):
		if s[i] == '*':
			star += 1
		else:
			if star > 0:
				digits.append(star * k + 1)
			star = 0
	if star > 0:
		digits.append(star * k + 1)
	represent = []
	x -= 1
	while x > 0:
		d = digits.pop()
		represent.append(x % d)
		x = x // d
	represent += len(digits) * [0]
	ans = []
	index = 0
	while index < n:
		if s[index] == 'a':
			ans.append('a')
			index += 1
			continue
		while index < n and s[index] == '*':
			index += 1
		ans.append(represent.pop() * 'b')
	ans = ''.join(ans)
	print(ans)
T = int(input())
t = 1
while t <= T:
	main(t)
	t += 1


import itertools

def solve(n, k, x, s):
	gr = [(key, list(group)) for (key, group) in itertools.groupby(list(s))]
	patters = [1] * len(gr)
	for (i, (key, group)) in enumerate(gr):
		if key == 'a':
			continue
		else:
			patters[i] = k * len(list(group)) + 1
	counts = [0] * len(gr)
	count = 1
	x -= 1
	for i in range(len(gr) - 1, -1, -1):
		p = patters[i]
		(key, group) = gr[i]
		if key == 'a':
			continue
		counts[i] = x % p
		x = x // p
		if x == 0:
			break
	ans = ''
	for (i, (key, group)) in enumerate(gr):
		if key == 'a':
			ans += ''.join(group)
		else:
			ans += 'b' * counts[i]
	return ans

def main():
	ans = []
	t = int(input())
	for _ in range(t):
		(n, k, x) = map(int, input().split())
		s = input()
		ans.append(solve(n, k, x, s))
	for a in ans:
		print(a)
main()


cases = int(input())
for i in range(cases):
	(n, k, x) = [int(x) for x in input().split()]
	liste = [val for val in input()]
	x -= 1
	numstars = []
	num_stars_in_group = 0
	for i in range(len(liste) - 1, -1, -1):
		if liste[i] == '*':
			num_stars_in_group += 1
		elif liste[i] == 'a' and num_stars_in_group > 0:
			numstars.append(num_stars_in_group)
			num_stars_in_group = 0
	if num_stars_in_group != 0:
		numstars.append(num_stars_in_group)
	num_bs = []
	for i in range(len(numstars)):
		num_bs.append(x % (numstars[i] * k + 1) * 'b')
		x = x // (numstars[i] * k + 1)
	star = False
	finished_list = []
	counter = 0
	for i in range(len(liste) - 1, -1, -1):
		if liste[i] == '*' and counter < len(num_bs) and (star == False):
			star = True
			finished_list.append(num_bs[counter])
			counter += 1
		elif liste[i] == 'a':
			star = False
			finished_list.append(liste[i])
	print(''.join(finished_list[::-1]))


import heapq
import sys
import math
from collections import deque
from bisect import bisect_left, bisect_right
I = sys.stdin.readline
II = lambda : int(I())
IN = lambda x: map(int, x.split())
FN = lambda x: map(float, x.split())
L = lambda x: list(IN(x))
M = 1000000007
P = print
T = True
F = False
for _ in range(II()):
	(n, k, x) = IN(I())
	x -= 1
	s = I()
	st = []
	i = 0
	lc = s[0]
	li = 0
	while i < n:
		while s[i] == lc:
			i += 1
		st.append(i - li)
		lc = s[i]
		li = i
	zx = len(st) - 1
	if s[-2] == 'a':
		zx -= 1
	wt = [1]
	f = -1
	for i in range(zx, -1, -2):
		twt = wt[-1] * (st[i] * k + 1)
		wt.append(twt)
		if x < twt:
			f = i
			break
	res = []
	i = 0
	if s[0] == 'a':
		i += 1
		res.append('a' * st[0])
	while i < len(st):
		if i >= f:
			break
		i += 1
		if i < len(st):
			res.append('a' * st[i])
		i += 1
	while i < len(st):
		(q, x) = divmod(x, wt[-2])
		wt.pop()
		res.append(q * 'b')
		i += 1
		if i < len(st):
			res.append('a' * st[i])
		i += 1
	print(*res, sep='')


for t in range(int(input())):
	[n, k, x] = [int(x) for x in input().split()]
	s = input()
	s = s[::-1]
	x -= 1
	res = ''
	i = 0
	while i < n:
		if s[i] == 'a':
			res += 'a'
		else:
			j = i
			while j + 1 < n and s[j + 1] == s[i]:
				j += 1
			count = (j - i + 1) * k + 1
			res += 'b' * (x % count)
			x //= count
			i = j
		i += 1
	print(res[::-1])


import math
t = int(input())
for case in range(t):
	(n, k, x) = list(map(int, input().split()))
	s = input()
	prod = []
	i = n - 1
	while i >= 0:
		if s[i] == '*':
			cnt = 1
			j = i - 1
			while j >= 0 and s[j] == '*':
				cnt += 1
				j -= 1
			i = j
			if len(prod) == 0:
				prod.append(cnt * k + 1)
			else:
				prod.append((cnt * k + 1) * prod[-1])
		else:
			i -= 1
	prod = prod[::-1]
	m = len(prod)
	idx = 0
	ans = [''] * m
	for i in range(m - 1, -1, -1):
		if prod[i] >= x:
			idx = i
			break
	for i in range(idx, m):
		if i == m - 1:
			ans[i] = 'b' * (x - 1)
			continue
		if prod[i] >= x:
			p = math.ceil(x / prod[i + 1]) - 1
			ans[i] = 'b' * p
			x -= p * prod[i + 1]
	(i, j) = (0, 0)
	string = ''
	while i < n:
		if s[i] == '*':
			string += ans[j]
			j += 1
			while i < n and s[i] == '*':
				i += 1
		else:
			string += s[i]
			i += 1
	print(string)


import re

def solve(k, x, a):
	stars = re.findall('\\*+', a)
	aa = re.findall('a+', a)
	d = [k * len(si) + 1 for si in stars] + [1]
	l_d = len(d)
	INF = 10 ** 20
	for i in range(l_d - 1, 0, -1):
		d[i - 1] *= d[i]
		if d[i - 1] >= INF:
			d[i - 1] = INF
	b_cnts = [0] * l_d
	for i in range(1, l_d):
		b_cnts[i] = x // d[i]
		x -= b_cnts[i] * d[i]
	res = []
	for (ai, bi) in zip(aa, b_cnts[1:]):
		res.append(ai)
		res.append('b' * bi)
	if len(aa) > len(d) - 1:
		res.append(aa[-1])
	return ''.join(res)
t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	x -= 1
	a = input()
	flag = False
	if a[0] == '*':
		flag = True
		a = 'a' + a
	res = solve(k, x, a)
	if not flag:
		print(res)
	else:
		print(res[1:])


def solve():
	for _ in range(int(input())):
		(n, k, x) = map(int, input().split())
		x -= 1
		s = input()[::-1]
		res = []
		i = 0
		while i < n:
			if s[i] == 'a':
				res.append(s[i])
			else:
				j = i
				while j + 1 < n and s[j + 1] == s[i]:
					j += 1
				cur = (j - i + 1) * k + 1
				res.append('b' * (x % cur))
				x //= cur
				i = j
			i += 1
		print(''.join(res[::-1]))
solve()


from collections import defaultdict, deque, Counter
from sys import stdin, stdout
from heapq import heappush, heappop
import math
import io
import os
import math
import bisect

def isPrime(x):
	for i in range(2, x):
		if i * i > x:
			break
		if x % i == 0:
			return False
	return True

def ncr(n, r, p):
	num = den = 1
	for i in range(r):
		num = num * (n - i) % p
		den = den * (i + 1) % p
	return num * pow(den, p - 2, p) % p

def primeFactors(n):
	l = []
	while n % 2 == 0:
		l.append(2)
		n = n / 2
	for i in range(3, int(math.sqrt(n)) + 1, 2):
		while n % i == 0:
			l.append(int(i))
			n = n / i
	if n > 2:
		l.append(n)
	return list(set(l))

def power(x, y, p):
	res = 1
	x = x % p
	if x == 0:
		return 0
	while y > 0:
		if y & 1 == 1:
			res = res * x % p
		y = y >> 1
		x = x * x % p
	return res

def sieve(n):
	prime = [True for i in range(n + 1)]
	p = 2
	while p * p <= n:
		if prime[p] == True:
			for i in range(p * p, n + 1, p):
				prime[i] = False
		p += 1
	return prime

def digits(n):
	c = 0
	while n > 0:
		n //= 10
		c += 1
	return c

def ceil(n, x):
	if n % x == 0:
		return n // x
	return n // x + 1

def mapin():
	return map(int, input().split())
t = int(input())
for _ in range(t):
	(n, k, xi) = mapin()
	s = list(input())
	ast = s.count('*')
	x = 0
	l = []
	for i in range(n):
		if s[i] == '*':
			x += 1
		else:
			l.append(x * k)
			x = 0
	l.append(x * k)
	ll = [0] * len(l)
	l.reverse()
	x = xi - 1
	for i in range(len(l)):
		ll[i] = x % (l[i] + 1)
		x = x // (l[i] + 1)
	ll.reverse()
	ss = []
	for i in range(len(ll)):
		ss.append('b' * ll[i])
		ss.append('a')
	ss.pop(-1)
	print(''.join(ss))


t = int(input())
while t > 0:
	t -= 1
	(n, k, x) = map(int, input().split())
	s = input()
	sa = list(filter(lambda x: x != '', s.split('a')))
	sz = [len(x) * k + 1 for x in sa]
	suff = [1 for x in range(len(sz) + 1)]
	for i in range(len(sz) - 1, -1, -1):
		suff[i] = sz[i] * suff[i + 1]
	j = 0
	for i in range(len(sz) - 1, -1, -1):
		if suff[i] >= x:
			j = i
			break
	add = [0 for x in range(len(sz))]
	for i in range(j, len(sz)):
		to_add = (x - 1) // suff[i + 1]
		x -= to_add * suff[i + 1]
		add[i] = to_add
	res = ''
	j = 0
	i = 0
	while i < n:
		if s[i] == 'a':
			res += 'a'
			i += 1
		else:
			while i < n and s[i] == '*':
				i += 1
			if j < len(add):
				res += 'b' * add[j]
				j += 1
	print(res)


for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	blocks = [0]
	for c in s[::-1] + 'a':
		if c == 'a':
			if blocks[-1]:
				blocks.append(0)
		else:
			blocks[-1] += 1
	blocks.pop()
	x -= 1
	ans = [0] * len(blocks)
	for (i, b) in enumerate(blocks):
		(ans[i], x) = (x % (b * k + 1), x // (b * k + 1))
	p = ''
	last_ast = False
	for c in s:
		if c == 'a':
			p += c
			last_ast = False
		else:
			if not last_ast:
				p += 'b' * ans.pop()
			last_ast = True
	print(p)


import array
import bisect
import heapq
import math
import collections
import sys
import copy
from functools import reduce
import decimal
from io import BytesIO, IOBase
import os
import itertools
import functools
from types import GeneratorType
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
graphDict = collections.defaultdict
queue = collections.deque

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		to = f(*args, **kwargs)
		if stack:
			return to
		else:
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						return to
					to = stack[-1].send(to)
	return wrappedfunc

class Graphs:

	def __init__(self):
		self.graph = graphDict(set)

	def add_edge(self, u, v):
		self.graph[u].add(v)
		self.graph[v].add(u)

	def dfs_utility(self, nodes, visited_nodes, colors, parity, level):
		global count
		if nodes == 1:
			colors[nodes] = -1
		elif len(self.graph[nodes]) == 1 and parity % 2 == 0:
			if q == 1:
				colors[nodes] = 1
			else:
				colors[nodes] = -1
				count += 1
		elif parity % 2 == 0:
			colors[nodes] = -1
		else:
			colors[nodes] = 1
		visited_nodes.add(nodes)
		for neighbour in self.graph[nodes]:
			new_level = level + 1
			if neighbour not in visited_nodes:
				self.dfs_utility(neighbour, visited_nodes, colors, level - 1, new_level)

	def dfs(self, node):
		Visited = set()
		color = collections.defaultdict()
		self.dfs_utility(node, Visited, color, 0, 0)
		return color

	def bfs(self, node, f_node):
		count = float('inf')
		visited = set()
		level = 0
		if node not in visited:
			queue.append([node, level])
			visited.add(node)
		flag = 0
		while queue:
			parent = queue.popleft()
			if parent[0] == f_node:
				flag = 1
				count = min(count, parent[1])
			level = parent[1] + 1
			for item in self.graph[parent[0]]:
				if item not in visited:
					queue.append([item, level])
					visited.add(item)
		return count if flag else -1
		return False

class Tree:

	def __init__(self, data):
		self.data = data
		self.left = None
		self.right = None

def inorder(node, lis):
	if node:
		inorder(node.left, lis)
		lis.append(node.data)
		inorder(node.right, lis)
	return lis

def leaf_node_sum(root):
	if root is None:
		return 0
	if root.left is None and root.right is None:
		return root.data
	return leaf_node_sum(root.left) + leaf_node_sum(root.right)

def hight(root):
	if root is None:
		return -1
	if root.left is None and root.right is None:
		return 0
	return max(hight(root.left), hight(root.right)) + 1

class UnionFind:
	parents = []
	sizes = []
	count = 0

	def __init__(self, n):
		self.count = n
		self.parents = [i for i in range(n)]
		self.sizes = [1 for i in range(n)]

	def find(self, i):
		if self.parents[i] == i:
			return i
		else:
			self.parents[i] = self.find(self.parents[i])
			return self.parents[i]

	def unite(self, i, j):
		root_i = self.find(i)
		root_j = self.find(j)
		if root_i == root_j:
			return
		elif root_i < root_j:
			self.parents[root_j] = root_i
			self.sizes[root_i] += self.sizes[root_j]
		else:
			self.parents[root_i] = root_j
			self.sizes[root_j] += self.sizes[root_i]

	def same(self, i, j):
		return self.find(i) == self.find(j)

	def size(self, i):
		return self.sizes[self.find(i)]

	def group_count(self):
		return len(set((self.find(i) for i in range(self.count))))

	def answer(self, extra, p, q):
		dic = collections.Counter()
		for q in range(n):
			dic[self.find(q)] = self.size(q)
		hq = list(dic.values())
		heapq._heapify_max(hq)
		ans = -1
		for z in range(extra + 1):
			if hq:
				ans += heapq._heappop_max(hq)
			else:
				break
		return ans

def rounding(n):
	return int(decimal.Decimal(f'{n}').to_integral_value())

def factors(n):
	return set(reduce(list.__add__, ([i, n // i] for i in range(1, int(n ** 0.5) + 1) if n % i == 0)))

def p_sum(array):
	return list(itertools.accumulate(array))

def base_change(nn, bb):
	if nn == 0:
		return [0]
	digits = []
	while nn:
		digits.append(int(nn % bb))
		nn //= bb
	return digits[::-1]

def diophantine(a: int, b: int, c: int):
	(d, x, y) = extended_gcd(a, b)
	r = c // d
	return (r * x, r * y)

@bootstrap
def extended_gcd(a: int, b: int):
	if b == 0:
		(d, x, y) = (a, 1, 0)
	else:
		(d, p, q) = (yield extended_gcd(b, a % b))
		x = q
		y = p - q * (a // b)
	yield (d, x, y)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self, **kwargs):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def inp():
	return sys.stdin.readline().strip()

def map_inp(v_type):
	return map(v_type, inp().split())

def list_inp(v_type):
	return list(map_inp(v_type))
for _ in range(int(inp())):
	(n, k, x) = map_inp(int)
	x -= 1
	s = list(inp())
	s.reverse()
	res = []
	i = 0
	while i < n:
		if s[i] == 'a':
			res.append(s[i])
		else:
			j = i
			while j + 1 < n and s[j + 1] == s[i]:
				j += 1
			cur = (j - i + 1) * k + 1
			res.append('b' * (x % cur))
			x //= cur
			i = j
		i += 1
	res.reverse()
	print(''.join(res))


t = int(input())
for i in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	ck = [0]
	if s[0] == 'a':
		a = ['']
	else:
		a = ['', '']
	for i in s:
		if i == '*':
			ck[-1] += 1
		elif ck[-1] != 0:
			ck.append(0)
		if i == 'a':
			a[-1] += 'a'
		elif a[-1] != '':
			a.append('')
	if ck[-1] == 0:
		ck.pop(-1)
	b = []
	x -= 1
	for i in ck[::-1]:
		b.append(x % (i * k + 1))
		x = x // (i * k + 1)
		if x == 0:
			break
	change_s = ''
	while len(a) > 0:
		if len(b) == 0:
			b.append(0)
		change_s += a.pop(-1) + 'b' * b.pop(0)
	print(change_s[::-1])


def bas(n, k, x, s):
	i = 0
	dc = []
	cd = []
	st = ''
	while i < len(s):
		if s[i] == '*':
			j = i + 1
			if j < len(s):
				while s[j] == '*':
					j = j + 1
					if j >= len(s):
						break
			cd.append(j - i)
			i = j - 1
		i = i + 1
	i = 0
	while i < len(s):
		if s[i] == 'a':
			j = i + 1
			if j < len(s):
				while s[j] == 'a':
					j = j + 1
					if j >= len(s):
						break
			dc.append(j - i)
			i = j - 1
		i = i + 1
	i = 0
	while i < len(cd):
		cd[i] = cd[i] * k + 1
		i = i + 1
	i = 0
	while i < len(dc):
		dc[i] = dc[i] * 'a'
		i = i + 1
	i = len(cd) - 1
	p = 1
	while i >= 0:
		if p >= x:
			break
		p = p * cd[i]
		i = i - 1
	v = i + 1
	i = len(cd) - 1
	lans = [0] * len(cd)
	while i >= v:
		lans[i] = x % cd[i]
		lans[i] = lans[i] - 1
		if lans[i] < 0:
			lans[i] = lans[i] + cd[i]
		if x % cd[i] != 0:
			x = x // cd[i] + 1
		else:
			x = x // cd[i]
		i = i - 1
	i = 0
	while i < len(lans):
		if lans[i] == 0:
			lans[i] = ''
		else:
			lans[i] = lans[i] * 'b'
		i = i + 1
	ans = ''
	if s[0] == 'a':
		i = 0
		j = 0
		while i < len(dc):
			ans = ans + dc[i]
			if j < len(lans):
				ans = ans + lans[j]
				j = j + 1
			i = i + 1
	else:
		i = 0
		j = 0
		while i < len(lans):
			ans = ans + lans[i]
			if j < len(dc):
				ans = ans + dc[j]
				j = j + 1
			i = i + 1
	return ans
t = int(input())
l = []
for x in range(t):
	s1 = str(input())
	s2 = str(input())
	l.append([s1, s2])
la = []
for x in l:
	lt = x[0].split(' ')
	l1 = []
	for y in lt:
		l1.append(int(y))
	s = x[1]
	n = l1[0]
	k = l1[1]
	x = l1[2]
	ans = bas(n, k, x, s)
	la.append(ans)
for x in la:
	print(x)


import sys
tcases = int(input())
for t in range(tcases):
	(n, k, x) = map(int, sys.stdin.readline().split())
	s = sys.stdin.readline()[:-1]
	cnt = [0]
	cntA = [0]
	if s[0] != 'a':
		cntA.append(0)
	for c in s:
		if c == 'a':
			if cnt[-1] != 0:
				cnt.append(0)
			cntA[-1] += 1
		else:
			if cntA[-1] != 0:
				cntA.append(0)
			cnt[-1] += k
	if cnt[-1] == 0:
		cnt.pop()
	if cntA[-1] == 0:
		cntA.pop()
	b = [0] * len(cnt)
	x -= 1
	while x > 0:
		(acc, i) = (1, len(cnt) - 1)
		while i >= 0 and acc * (cnt[i] + 1) <= x:
			acc *= cnt[i] + 1
			i -= 1
		assert i >= 0
		y = x // acc
		b[i] = y
		x = x % acc
	ans = []
	for i in range(len(cntA)):
		if cntA[i] > 0:
			ans.append(cntA[i] * 'a')
		if i < len(b) and b[i] > 0:
			ans.append(b[i] * 'b')
	print(''.join(ans))


import sys
input = sys.stdin.readline

def iinput():
	return int(input())

def sinput():
	return input().rstrip()

def i0input():
	return int(input()) - 1

def linput():
	return list(input().split())

def liinput():
	return list(map(int, input().split()))

def miinput():
	return map(int, input().split())

def li0input():
	return list(map(lambda x: int(x) - 1, input().split()))

def mi0input():
	return map(lambda x: int(x) - 1, input().split())
INF = 10 ** 20
MOD = 1000000007

def rle(s):
	(tmp, count, ans1, ans2) = (s[0], 1, [], [])
	for i in range(1, len(s)):
		if tmp == s[i]:
			count += 1
		else:
			ans1.append(tmp)
			ans2.append(count)
			tmp = s[i]
			count = 1
	ans1.append(tmp)
	ans2.append(count)
	return (ans1, ans2)
t = iinput()
for _ in [0] * t:
	(n, k, x) = liinput()
	x -= 1
	s = sinput()
	tmp = s.count('*')
	if tmp == 0:
		print(s)
		continue
	(ss, ctr) = rle(s)
	res = []
	for (c, cn) in zip(ss[::-1], ctr[::-1]):
		if c == 'a':
			continue
		else:
			res.append(x % (k * cn + 1))
			x //= k * cn + 1
	ans = ''
	for (c, cn) in zip(ss, ctr):
		if c == 'a':
			ans += 'a' * cn
		else:
			tmp = res.pop()
			ans += 'b' * tmp
	print(ans)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	arr = []
	for i in s:
		if i == 'a':
			arr.append('a')
		elif len(arr) == 0:
			arr.append(1)
		elif arr[-1] == 'a':
			arr.append(1)
		else:
			arr[-1] += 1
	groups = [i for i in arr if i != 'a']
	val = [0 for i in groups]
	for i in range(len(groups)):
		current_strings = k * groups[i] + 1
		ahead_strings = 1
		for j in range(i + 1, len(groups)):
			ahead_strings *= k * groups[j] + 1
			if ahead_strings >= x:
				break
		val[i] = (x - 1) // ahead_strings
		x -= ahead_strings * val[i]
	(i, j) = (0, 0)
	ans = []
	while i < len(arr):
		if arr[i] == 'a':
			ans.append('a')
		else:
			ans.append('b' * val[j])
			j += 1
		i += 1
	print(''.join(ans))


def solve():
	[N, K, X] = [int(x) for x in input().split()]
	SS = list(input())
	if SS.count('a') == len(SS):
		print(''.join(SS))
		return
	S = list(reversed(SS))
	sp = [0]
	for i in range(len(S)):
		if S[i] == '*':
			sp[-1] += 1
		elif sp[-1] != 0:
			sp.append(0)
	if sp[-1] == 0:
		sp.pop()
	cur = 0
	p = sp[0] * K + 1
	pot = [p]
	sol = [0]
	while p < X:
		cur += 1
		p *= sp[cur] * K + 1
		pot.append(p)
		sol.append(0)
	X -= 1
	for i in range(cur, 0, -1):
		sol[i] = X // pot[i - 1]
		X %= pot[i - 1]
	sol[0] = X
	sol = sol + [0] * (len(sp) - cur - 1)
	SSS = []
	cur = len(sol) - 1
	for i in range(len(SS)):
		if SS[i] == 'a':
			SSS.append('a')
		elif SS[i] == '*' and (i == 0 or SS[i - 1] != '*'):
			SSS.append('b' * sol[cur])
			cur -= 1
	print(''.join(SSS))
T = int(input())
for i in range(T):
	solve()


import sys

def ba_string(n, k, x, s):
	x -= 1
	output = ''
	s = s[::-1]
	m = 0
	for ch in s:
		if ch == 'a':
			if m > 0:
				if x > 0:
					p = x % (m * k + 1)
					x //= m * k + 1
					output += 'b' * p
			output += ch
			m = 0
		else:
			m += 1
	if m > 0:
		if x > 0:
			p = x % (m * k + 1)
			x //= m * k + 1
			output += 'b' * p
	return output[::-1]
for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	sys.stdout.write(f'{ba_string(n, k, x, s)}\n')


t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	s = s[::-1]
	ans = ''
	i = 0
	x -= 1
	while i < n:
		if s[i] == 'a':
			ans += 'a'
		else:
			j = i
			while j + 1 < n and s[j + 1] == s[i]:
				j += 1
			c = (j - i + 1) * k + 1
			c1 = x % c
			ans += 'b' * c1
			x = x // c
			i = j
		i += 1
	print(ans[::-1])


import sys, math
INF = float('inf')
mod = 10 ** 9 + 7
input = lambda : sys.stdin.readline().rstrip()
li = lambda : list(map(int, input().split()))
from itertools import groupby

def RLE(s: str) -> list:
	encoded = []
	for (key, group) in groupby(s):
		encoded.append([key, len(list(group))])
	return encoded
t = int(input())
output = []
for _ in range(t):
	(N, K, X) = li()
	S = list(input())
	if X == 1:
		cnt = S.count('a')
		output.append('a' * cnt)
		continue
	S = RLE(S)
	su = 1
	lst = []
	for (k, n) in S[::-1]:
		n *= K
		n += 1
		if k == 'a':
			continue
		if n * su >= X:
			su = n * su
			break
		else:
			su *= n
			lst.append(su)
	lst2 = []
	X -= 1
	for i in range(len(lst))[::-1]:
		waru = X // lst[i]
		lst2.append(waru)
		X %= lst[i]
	lst2.append(X)
	cnt = len(lst2) - 1
	ans = [''] * len(S)
	for i in range(len(S))[::-1]:
		(k, n) = S[i]
		if k == 'a':
			ans[i] = 'a' * n
		elif cnt >= 0:
			ans[i] = 'b' * lst2[cnt]
			cnt -= 1
	output.append(''.join(ans))
for a in output:
	print(a)


def main():
	t = int(input())
	allans = []
	for _ in range(t):
		(n, k, x) = readIntArr()
		s = input()
		x -= 1
		arr = []
		cnts = 0
		for i in range(n - 1, -1, -1):
			if s[i] == 'a':
				arr.append('b' * (x % (cnts + 1)))
				x //= cnts + 1
				cnts = 0
				arr.append('a')
			else:
				cnts += k
		arr.append('b' * (x % (cnts + 1)))
		arr.reverse()
		allans.append(''.join(arr))
	multiLineArrayPrint(allans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(defaultValFactory, dimensionArr):
	dv = defaultValFactory
	da = dimensionArr
	if len(da) == 1:
		return [dv() for _ in range(da[0])]
	else:
		return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(a, b, c):
	print('? {} {} {}'.format(a, b, c))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ansArr):
	print('! {}'.format(' '.join([str(x) for x in ansArr])))
	sys.stdout.flush()
inf = float('inf')
from math import gcd, floor, ceil
import math
for _abc in range(1):
	main()


import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
input = lambda : sys.stdin.readline().rstrip()
import bisect, string, math, time, functools, random, fractions
from bisect import *
from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
from itertools import permutations, combinations, groupby
rep = range
R = range

def I():
	return int(input())

def LI():
	return [int(i) for i in input().split()]

def SLI():
	return sorted([int(i) for i in input().split()])

def LI_():
	return [int(i) - 1 for i in input().split()]

def S_():
	return input()

def IS():
	return input().split()

def LS():
	return [i for i in input().split()]

def NI(n):
	return [int(input()) for i in range(n)]

def NI_(n):
	return [int(input()) - 1 for i in range(n)]

def NLI(n):
	return [[int(i) for i in input().split()] for i in range(n)]

def NLI_(n):
	return [[int(i) - 1 for i in input().split()] for i in range(n)]

def StoLI():
	return [ord(i) - 97 for i in input()]

def ItoS(n):
	return chr(n + 97)

def LtoS(ls):
	return ''.join([chr(i + 97) for i in ls])

def RLI(n=8, a=1, b=10):
	return [random.randint(a, b) for i in range(n)]

def RI(a=1, b=10):
	return random.randint(a, b)

def INP():
	N = 10
	n = random.randint(2, N)
	mn = 1
	mx = 5
	a = [random.randint(mn, mx) for i in range(n)]
	s = [random.randint(mn, mx) for i in range(n)]
	return (n, a, s)

def Rtest(T):
	(case, err) = (0, 0)
	for i in range(T):
		inp = INP()
		a1 = naive(*inp)
		a2 = solve(*inp)
		if a1 != a2:
			(x, y) = a1
			(z, w) = a2
			cm = Comb(max(x, z))
			if cm.comb(x, y) == cm.comb(z, w):
				case += 1
				continue
			print(inp)
			print('naive', a1)
			print('solve', a2)
			err += 1
		case += 1
	print('Tested', case, 'case with', err, 'errors')

def GI(V, E, ls=None, Directed=False, index=1):
	org_inp = []
	g = [[] for i in range(V)]
	FromStdin = True if ls == None else False
	for i in range(E):
		if FromStdin:
			inp = LI()
			org_inp.append(inp)
		else:
			inp = ls[i]
		if len(inp) == 2:
			(a, b) = inp
			c = 1
		else:
			(a, b, c) = inp
		if index == 1:
			a -= 1
			b -= 1
		aa = (a, c)
		bb = (b, c)
		g[a].append(bb)
		if not Directed:
			g[b].append(aa)
	return (g, org_inp)

def RE(E):
	rt = [[] for i in range(len(E))]
	for i in range(len(E)):
		for (nb, d) in E[i]:
			rt[nb] += ((i, d),)
	return rt

def GGI(h, w, search=None, replacement_of_found='.', mp_def={'#': 1, '.': 0}, boundary=1):
	mp = [boundary] * (w + 2)
	found = {}
	for i in R(h):
		s = input()
		for char in search:
			if char in s:
				found[char] = (i + 1) * (w + 2) + s.index(char) + 1
				mp_def[char] = mp_def[replacement_of_found]
		mp += [boundary] + [mp_def[j] for j in s] + [boundary]
	mp += [boundary] * (w + 2)
	return (h + 2, w + 2, mp, found)

def TI(n):
	return GI(n, n - 1)

def accum(ls):
	rt = [0]
	for i in ls:
		rt += [rt[-1] + i]
	return rt

def bit_combination(n, base=2):
	rt = []
	for tb in R(base ** n):
		s = [tb // base ** bt % base for bt in R(n)]
		rt += [s]
	return rt

def gcd(x, y):
	if y == 0:
		return x
	if x % y == 0:
		return y
	while x % y != 0:
		(x, y) = (y, x % y)
	return y

def YN(x):
	print(['NO', 'YES'][x])

def Yn(x):
	print(['No', 'Yes'][x])

def show(*inp, end='\n'):
	if show_flg:
		print(*inp, end=end)
mo = 10 ** 9 + 7
mo = 998244353
inf = float('inf')
FourNb = [(-1, 0), (1, 0), (0, 1), (0, -1)]
EightNb = [(-1, 0), (1, 0), (0, 1), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)]
compas = dict(zip('WENS', FourNb))
cursol = dict(zip('LRUD', FourNb))
alp = [chr(ord('a') + i) for i in range(26)]
show_flg = False
show_flg = True
ans = 0
for _ in range(I()):
	(n, k, x) = LI()
	x -= 1
	s = input()
	if s.count('*') == 0:
		print(s)
		continue
	g = groupby(s)
	b = [[k, 0, len(list(it))] for (k, it) in g]
	s = [[c, t, mb, None] for (c, t, mb) in b if c == '*']
	t = 1
	i = j = 0
	for (c, _, mb, _) in s[::-1]:
		t *= mb * k + 1
		if t > x:
			j = i
		i += 1
		s[-i][-1] = mb * k + 1
	for i in range(-1, -j - 2, -1):
		(c, t, mb, com) = s[i]
		s[i][1] = x % com
		x //= com
	ans = []
	j = 0
	for (k, _, no) in b:
		if k == 'a':
			ans += ('a' * no,)
		else:
			ans += ('b' * s[j][1],)
			j += 1
	print(''.join(ans))


ans = []
for p in range(int(input())):
	a = input().split()
	a[0] = int(a[0])
	a[1] = int(a[1])
	a[2] = int(a[2]) - 1
	s = input()[::-1]
	s2 = s
	s = s + 'b'
	ps = 0
	step = 1
	for i in range(len(s)):
		if a[2] == 0:
			break
		if s[i] == '*':
			ps += 1
		elif ps != 0:
			s2 = s2.replace('*' * ps, 'b' * (a[2] % (a[1] * ps + 1)), 1)
			a[2] = a[2] // (a[1] * ps + 1)
			ps = 0
	ans.append(s2[::-1].replace('*', ''))
for i in ans:
	print(i)


import sys
input = lambda : sys.stdin.readline().rstrip()
INF = 10 ** 19

def solve():
	(n, k, x) = map(int, input().split())
	s = list(input())
	ren = []
	cnt = 0
	for i in range(n):
		if s[i] == '*':
			cnt += 1
		else:
			ren.append(cnt)
			cnt = 0
	t = []
	for i in range(n):
		if s[i] == 'a':
			t.append(s[i])
		elif s[i] == '*' and i == n - 1:
			t.append('*')
		elif s[i] == '*' and s[i + 1] == 'a':
			t.append('*')
	s = t
	n = len(s)
	ren.append(cnt)
	l = []
	for i in ren:
		if i > 0:
			l.append(i * k)
	ans = []
	x -= 1
	for i in range(len(l) - 1, -1, -1):
		ans.append(x % (l[i] + 1))
		x //= l[i] + 1
	for i in range(n):
		if s[i] == '*':
			if not ans:
				s[i] = ''
				continue
			s[i] = 'b' * ans.pop()
	print(''.join(s))
t = int(input())
for _ in range(t):
	solve()


from __future__ import division, print_function
from math import inf
import itertools
import sys
if sys.version_info[0] < 3:
	input = raw_input
	range = xrange
	filter = itertools.ifilter
	map = itertools.imap
	zip = itertools.izip
read_int_vec = lambda x: [int(c) for c in x.split(' ')]
from math import inf, sqrt
from itertools import groupby

def solution(s, n, k, x):
	x -= 1
	s = list(s)
	s = s[::-1]
	i = 0
	res = []
	while i < n:
		if s[i] == 'a':
			res.append('a')
		else:
			j = i
			while j + 1 < n and s[j + 1] == s[i]:
				j += 1
			curr = (j - i + 1) * k + 1
			res.append('b' * (x % curr))
			x //= curr
			i = j
		i += 1
	return ''.join(res[::-1])
n_tests = int(input())
for _ in range(n_tests):
	(n, k, x) = read_int_vec(input())
	s = input()
	print(solution(s, n, k, x))


import sys
input = sys.stdin.readline

def solve(n, k, x, string):
	x -= 1
	newList = []
	mul = []
	temp = 0
	for i in range(n):
		if string[i] == 'a':
			if temp > 0:
				newList.append(temp + 1)
				mul.append(temp + 1)
				temp = 0
			newList.append(string[i])
		elif string[i] == '*':
			temp += k
			if i == n - 1:
				newList.append(temp + 1)
				mul.append(temp + 1)
				temp = 0
	mul.append(1)
	for i in range(len(mul) - 2, 0, -1):
		mul[i] = mul[i] * mul[i + 1]
	mul = mul[1:]
	ans = ''
	lastIndex = 0
	for i in range(len(newList)):
		if newList[i] == 'a':
			ans += 'a'
		else:
			t = x // mul[lastIndex]
			ans += t * 'b'
			x -= t * mul[lastIndex]
			lastIndex += 1
	return ans
t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	string = input()
	print(solve(n, k, x, string))


import math
from sys import stdin, stdout

def test_case():
	(n, k, x) = [int(x) for x in stdin.readline().rstrip().split()]
	a = stdin.readline().rstrip()
	o = []
	for i in range(n):
		if a[i] == 'a':
			o.append('a')
		elif o and o[-1] != 'a':
			o[-1] += k
		else:
			o.append(k)
	x = x - 1
	answer = []
	mul = 1
	for e in reversed(o):
		if e == 'a':
			answer.append('a')
		else:
			if x == 0:
				continue
			for i in range(x % (e + 1)):
				answer.append('b')
			x = x // (e + 1)
	answer.reverse()
	print(''.join(answer))
t = int(stdin.readline())
for i in range(t):
	test_case()


def fun(arr, x):
	y = 1
	i = 0
	while y < x:
		y *= arr[i]
		i += 1
	i -= 1
	y = y // arr[i]
	z = y
	y = 0
	j = 0
	while y < x:
		y += z
		j += 1
	j -= 1
	return [i, j, y - z]
for _ in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	arr = []
	c = 0
	flag = True
	for i in s:
		if i == 'a':
			if flag:
				arr.append(c * k + 1)
				c = 0
				flag = False
		else:
			c += 1
			flag = True
	if flag:
		arr.append(c * k + 1)
	if s[0] == 'a':
		arr.pop(0)
	arr = arr[::-1]
	ans = [0] * len(arr)
	sol = ''
	while x > 1:
		coord = fun(arr, x)
		(i, j) = (coord[0], coord[1])
		x -= coord[2]
		ans[i] = j
	ans = ans[::-1]
	flag = True
	j = 0
	for i in s:
		if i == 'a':
			sol += 'a'
			flag = True
		elif flag:
			sol += 'b' * ans[j]
			j += 1
			flag = False
	if sol == '':
		print('b')
	else:
		print(sol)


import math, sys
input = sys.stdin.readline
S = lambda : input().rstrip()
I = lambda : int(S())
M = lambda : map(int, S().split())
L = lambda : list(M())
mod1 = 1000000007
mod2 = 998244353
for _ in range(I()):
	(n, k, x) = M()
	s = S()[::-1]
	i = 0
	ans = []
	x -= 1
	while i < n:
		if s[i] == 'a':
			ans.append('a')
			i += 1
		else:
			j = i + 1
			while j < n and s[j] == '*':
				j += 1
			c = (j - i) * k + 1
			ans.append('b' * (x % c))
			x //= c
			i = j
	print(''.join(ans[::-1]))


import os
import sys
from io import BytesIO, IOBase
_print = print
BUFSIZE = 8192

def dbg(*args, **kwargs):
	_print('\x1b[95m', end='')
	_print(*args, **kwargs)
	_print('\x1b[0m', end='')

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def inp():
	return sys.stdin.readline().rstrip()

def mpint():
	return map(int, inp().split(' '))

def itg():
	return int(inp())

def split_consecutive(sorted_data, cmp=lambda a, b: a == b):
	result = []
	group = []
	prev = None
	for item in sorted_data:
		if not group or cmp(prev, item):
			group.append(item)
		else:
			result.append(group)
			group = [item]
		prev = item
	if group:
		result.append(group)
	return result
from itertools import accumulate
from operator import mul

def solve():
	(n, k, x) = mpint()
	s = inp()
	nums = []
	group = split_consecutive(s)
	for lst in group:
		if lst[0] == '*':
			nums.append(len(lst) * k + 1)
	nums = list(accumulate(reversed(nums), mul))
	if nums:
		del nums[-1]
	nums.reverse()
	nums.append(1)
	x -= 1
	j = 0
	for (i, lst) in enumerate(group):
		if lst[0] == 'a':
			group[i] = 'a' * len(lst)
		else:
			(q, x) = divmod(x, nums[j])
			j += 1
			group[i] = 'b' * q
	return ''.join(group)

def main():
	for _ in range(itg()):
		print(solve())
DEBUG = 0
URL = 'https://codeforces.com/contest/1620/problem/C'
if DEBUG == 1:
	import requests
	from ACgenerator.Y_Test_Case_Runner import TestCaseRunner
	runner = TestCaseRunner(main, URL)
	inp = runner.input_stream
	print = runner.output_stream
	runner.checking()
else:
	if DEBUG != 2:
		dbg = lambda *args, **kwargs: ...
		(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
	if DEBUG == 3:

		def print(*args, **kwargs):
			_print(*args, **kwargs)
			sys.stdout.flush()
	main()


import os
import sys
from io import BytesIO, IOBase
from types import GeneratorType
from collections import defaultdict
BUFSIZE = 8192

def bootstrap(f, stack=[]):

	def fun(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return fun

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
import math
t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	b = []
	for j in s:
		b.append(j)
	res = []
	curr = 0
	for i in range(n):
		if b[i] == 'a':
			res.append(curr * k + 1)
			curr = 0
		else:
			curr += 1
	res.append(curr * k + 1)
	ans = []
	l = len(res)
	j = l - 1
	last = 1
	req = []
	while j >= 0:
		if curr <= x:
			curr = res[j] * last
		else:
			curr = curr
		req.append(curr)
		last = curr
		j += -1
	req.reverse()
	cnt = [0 for i in range(l)]
	while x > 1:
		li = 0
		ri = l - 1
		while li < ri:
			m = (li + ri) // 2
			if req[m] < x:
				ri = m - 1
			elif ri == li + 1:
				if req[ri] >= x:
					li = ri
				else:
					ri = li
			else:
				li = m
		j = li
		if j == l - 1:
			curr = 1
		else:
			curr = req[j + 1]
		r = x // curr
		if x % curr == 0:
			r -= 1
		x -= r * curr
		cnt[j] = r
		last = curr
		if x <= 1:
			break
	ans = []
	for i in range(cnt[0]):
		ans.append('b')
	for i in range(1, l):
		ans.append('a')
		for j in range(cnt[i]):
			ans.append('b')
	print(''.join(ans))


for t in range(int(input())):
	(n, k, x) = map(int, input().split())
	s = input()
	x -= 1
	ans = ''
	bs = 0
	for sym in s[::-1]:
		if sym == '*':
			bs += 1
		elif bs != 0:
			ans = 'a' + 'b' * (x % (bs * k + 1)) + ans
			x //= bs * k + 1
			bs = 0
		else:
			ans = 'a' + ans
	if bs != 0:
		ans = 'b' * (x % (bs * k + 1)) + ans
	print(ans)


t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	s1 = list()
	a = 0
	pval = 1
	for i in range(len(s) - 1, -1, -1):
		if s[i] != '*' and a != 0:
			s1.append(pval)
			pval *= a * k + 1
			s1.append(s[i])
			a = 0
		elif s[i] == '*':
			a += 1
		else:
			s1.append(s[i])
	if a != 0:
		s1.append(pval)
		pval *= a * k + 1
		a = 0
	if x > pval:
		print('-1')
		continue
	for i in s1[::-1]:
		bcnt = 0
		if i.__class__ == int:
			if x > i:
				bcnt = x // i - 1
				if x % i != 0:
					bcnt = x // i
					x = x % i
				else:
					x = i
				print('b' * bcnt, end='')
		else:
			print(i, end='')
	print()


t = int(input())
for _ in range(t):
	(n, k, x) = map(int, input().split())
	s = input()
	l = 0
	blocks = []
	for i in range(len(s)):
		if s[i] == '*':
			l += 1
		elif l:
			blocks.append(l)
			l = 0
	if l:
		blocks.append(l)
		l = 0
	x -= 1
	p = [0] * len(blocks)
	for i in range(len(blocks) - 1, -1, -1):
		p[i] = x % (blocks[i] * k + 1)
		x //= blocks[i] * k + 1
	res = []
	i = 0
	j = 0
	while i < len(s):
		if s[i] == 'a':
			res.append('a')
			i += 1
		else:
			res += ['b'] * p[j]
			j += 1
			while i < len(s) and s[i] == '*':
				i += 1
	print(''.join(res))


t = int(input())
for i in range(0, t):
	a = input().split(' ')
	n = int(a[0])
	k = int(a[1])
	x = int(a[2])
	x -= 1
	s = input()
	sta = 0
	cnt = [0] * 2005
	pos = 0
	for c in s:
		if sta == 0 and c == 'a':
			cnt[pos] *= k
			cnt[pos] += 1
			pos += 1
			sta = 1
		if sta == 1 and c == '*':
			pos += 1
			sta = 0
		cnt[pos] += 1
	if pos % 2 == 0:
		cnt[pos] *= k
		cnt[pos] += 1
		temppos = pos
	else:
		temppos = pos - 1
	for j in range(temppos, -1, -2):
		temp = x % cnt[j]
		x = x // cnt[j]
		cnt[j] = temp
	for j in range(0, pos + 1):
		if j % 2 == 0:
			print('b' * cnt[j], end='')
		else:
			print('a' * cnt[j], end='')
	print()