description: Berland Music is a music streaming service built specifically to support Berland local artist. Its developers are currently working on a song recommendation module.
  
  So imagine Monocarp got recommended n songs, numbered from 1 to n. The i-th song had its predicted rating equal to p_i, where 1 ≤ p_i ≤ n and every integer from 1 to n appears exactly once. In other words, p is a permutation.
  
  After listening to each of them, Monocarp pressed either a like or a dislike button. Let his vote sequence be represented with a string s, such that s_i=0 means that he disliked the i-th song, and s_i=1 means that he liked it.
  
  Now the service has to re-evaluate the song ratings in such a way that:
  
    * the new ratings q_1, q_2, ..., q_n still form a permutation (1 ≤ q_i ≤ n; each integer from 1 to n appears exactly once); 
    * every song that Monocarp liked should have a greater rating than every song that Monocarp disliked (formally, for all i, j such that s_i=1 and s_j=0, q_i>q_j should hold). 
  
  
  
  Among all valid permutations q find the one that has the smallest value of ∑_{i=1}^n |p_i-q_i|, where |x| is an absolute value of x.
  
  Print the permutation q_1, q_2, ..., q_n. If there are multiple answers, you can print any of them.
  
  Input
  
  The first line contains a single integer t (1 ≤ t ≤ 10^4) — the number of testcases.
  
  The first line of each testcase contains a single integer n (1 ≤ n ≤ 2 ⋅ 10^5) — the number of songs.
  
  The second line of each testcase contains n integers p_1, p_2, ..., p_n (1 ≤ p_i ≤ n) — the permutation of the predicted ratings.
  
  The third line contains a single string s, consisting of n characters. Each character is either a 0 or a 1. 0 means that Monocarp disliked the song, and 1 means that he liked it.
  
  The sum of n over all testcases doesn't exceed 2 ⋅ 10^5.
  
  Output
  
  For each testcase, print a permutation q — the re-evaluated ratings of the songs. If there are multiple answers such that ∑_{i=1}^n |p_i-q_i| is minimum possible, you can print any of them.
  
  Example
  
  Input
  
  
  3
  2
  1 2
  10
  3
  3 1 2
  111
  8
  2 3 1 8 5 4 7 6
  01110001
  
  
  Output
  
  
  2 1
  3 1 2
  1 6 5 8 3 2 4 7
  
  Note
  
  In the first testcase, there exists only one permutation q such that each liked song is rating higher than each disliked song: song 1 gets rating 2 and song 2 gets rating 1. ∑_{i=1}^n |p_i-q_i|=|1-2|+|2-1|=2.
  
  In the second testcase, Monocarp liked all songs, so all permutations could work. The permutation with the minimum sum of absolute differences is the permutation equal to p. Its cost is 0.
solution: # cook your dish here
  # cook your dish here
  #-------------------imports-------#
  import sys
  import io,os
  import string
  from io import BytesIO, IOBase
  from os import path
  from collections import Counter,OrderedDict
  import itertools
  
  from itertools import chain, combinations
  import math
  import random
  import bisect
  from functools import reduce
  from sys import stdin,stdout
  from collections import OrderedDict
  from math import gcd,floor,sqrt,log
  from collections import defaultdict as dd
  from bisect import bisect_left as bl,bisect_right as br
  
  
  #------------------ONLINE JUDGE OR NOT-------#
  
  if(path.exists('input.txt')):
      sys.stdin = open("input.txt","r")
      sys.stdout = open("output.txt","w")
  else:
      input = sys.stdin.readline
      # input = io.BytesIO(os.read(0,os.fstat(0).st_size)).readline
  
  
  
  sys.setrecursionlimit(100000000)
  
  
  
  #---------------------pre made and input functions-------#
  simp    =lambda: int(input())
  strng  =lambda: input().strip()
  jn     =lambda x,l: x.join(map(str,l))
  strl   =lambda: list(input().strip())
  mul    =lambda: map(int,input().strip().split())
  mulf   =lambda: map(float,input().strip().split())
  seq    =lambda: list(map(int,input().strip().split()))
  ceil   =lambda x: int(x) if(x==int(x)) else int(x)+1
  ceildiv=lambda x,d: x//d if(x%d==0) else x//d+1
  flush  =lambda: stdout.flush()
  stdstr =lambda: stdin.readline()
  stdint =lambda: int(stdin.readline())
  stdpr  =lambda x: stdout.write(str(x))
  
  
  #------------functions---------------------
  
  #---------------------input-------
  
  n = simp()
  
  
  def if_its_binaryform_palindrome(n):
  
      res = 0
  
      k = n
      while k > 0:
          #to finish the job
          res = (res << 1) | (k & 1)
          k = k >> 1  
  
      return n == res
  
  
  
  
  
  
  def solve(a,d):
  
      dd = [0]*len(a)
      rr = {}
      s = {}
      for j in range(len(d)):
          if d[j]=='0':
              rr[j] = a[j]
          else:
              s[j] = a[j]
  
      i = 0
      rrr = {k: v for k, v in sorted(rr.items(), key=lambda item: item[1])}
      sss = {k: v for k, v in sorted(s.items(), key=lambda item: item[1])}
      rr_r = {}
      ss_s = {}
  
      # print(sss)
      while i < len(rr):
          rr_r[i] = i+1
          i+=1
  
      j = 0
          
      while j<len(sss):
  
          ss_s[i] = i+1
  
          i+=1
          j+=1 
  
      # print(ss_s)         
      # for i in range(len(rr)+1,len(s)+1):
      #     ss_s[i] = i-1
  
      # # print(rr_r)
      # print(ss_s)     
      zeroes = dict(zip(rrr.keys(), rr_r.values()))
      first = dict(zip(sss.keys(), ss_s.values()))
  
      # print(first)
      
      if len(zeroes)!=0:
  
          for i,j in zeroes.items():
              dd[i] = j
      
  
      if len(first)!=0:
          for i,j in first.items():
              dd[i] = j     
  
      return dd    
    
  
                  
  
              
  
  
      # i = 1
      # r = len(d)
      # rr = []
      # j = 0
      # while j<len(d):
      #     if d[j]=='0':
      #         rr.append(i)
      #         i+=1
      #     else:
      #         rr.append(r)
      #         r-=1
      #     j+=1
      # return rr            
  
  
   
  
  for i in range(n):
      d = simp()
      a = seq()
      r = strng()
      # d = seq()
      print(*solve(a,r))
      # r = strng()
      # t = strng()
      # d = strng()
      # t = seq()
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  def seive(n):
      """ preprocessing  """
   
      prime = [1 for i in range(n + 1)]
      p = 2
      while (p * p <= n):
           
          # this is prime number.
          if (prime[p] == 1):
               
              # Update all multiples of p in array
              for i in range(p ** 2, n + 1, p):
                  prime[i] = 0
                  
          p += 1
      prime[0]= 0
      prime[1]= 0
      
      # print(prime)
      for i in range(1,n+1):
          prime[i] += prime[i-1]
          
      return prime
  
  def list_of_prime_sieve(n):
  
      #an array of True True
      primes = [True]*(n+1)
      #changing o and 1 to False
      primes[0]==primes[1]==False
  
      #now for every true we find
      for i in range(2,int(n**(1/2))+1):
          if primes[i]==True:
              #we change their multiples to False
              for j in  range(i*i,n+1,i):
                  primes[j]=False
  
  
      list_primes = []
      for i in range(2,len(primes)):
          if primes[i]==True:
              list_primes.append(i)
  
      return list_primes
  
  def count_primes(a):
      return len(list_of_prime_sieve(a))    
  
  
  def gcdoftwo(a,b):
  
      #log(min(a,b))
      if a == 0:
          return b
      else:
          return gcdoftwo(b%a,a)
  
  def lcm(a,b): return (a*b//(gcdoftwo(a,b)))        
  
  def gcdofList(A): 
      res = A[0]
      for c in A[1::]:
          res = gcdoftwo(res , c) 
          if res == 1:
              return res
      return res         
  
  def binpow(a,b):
  
      #to calc a^b in log(n) time
  
  
      res = 1
  
  
      while b>0:
  
          if b&1:
              res = res*a
          a = a*a
          b>>=1
      return res        
  
  def fibo_in_logn(n):
      if n == 0:
          return [0, 1]
  
      p = fibo_in_logn(n >> 1)
      c = p.first * (2 * p.second - p.first)
      d = p.first * p.first + p.second * p.second
      if n & 1:
          return {d, c + d}
      else:
          return {c, d}
  
  
  
  
  
  def x_n_mod_m(a,b,m):
  
      #to calculate x^n mod m
  
      a  = a%m 
  
      res = 1
      while b>0:
          if b&1:
              res = res*a%m 
          a = a*a%m
          b>>=1
  
      return res
  
  
  
  
  def change_array(count,t):
  
      emp = []
      for i in range(len(t)):
          emp.append(count[t[i]])
      return emp    
  
  
  
  
  # prime = []
  
  def simpleSieve(limit):
  
      mark = [True for i in range(limit + 1)]
      p = 2
      while (p * p <= limit):
          if (mark[p] == True):
              for i in range(p * p, limit + 1, p):
                  mark[i] = False
          p += 1
      for p in range(2, limit):
          if mark[p]:
              prime.append(p)
              # print(p,end = " ")
      return prime        
  
  def segmentedSieve(n):
      limit = int(math.floor(math.sqrt(n)) + 1)
      t = []
      t += simpleSieve(limit)
  
      low = limit
      high = limit * 2
      while low < n:
          if high >= n:
              high = n
  
          mark = [True for i in range(limit + 1)]
  
          for i in range(len(prime)):
  
              loLim = int(math.floor(low / prime[i]) *
                                          prime[i])
              if loLim < low:
                  loLim += prime[i]
              for j in range(loLim, high, prime[i]):
                  mark[j - low] = False
  
          # t = []        
          for i in range(low, high):
              if mark[i - low]:
                  t.append(i)
                  # print(i, end = " ")
  
          low = low + limit
          high = high + limit
  
      return t
  
  
  
  
  mod=1000000007
  
  def occurrences(string, sub):
      count = start = 0
      while True:
          start = string.find(sub, start) + 1
          if start > 0:
              count+=1
          else:
              return count
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
      
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  