Problem:
Score : 1000 points

Problem Statement

There are 3^N people dancing in circle.
We denote with 0,1,\dots, 3^{N}-1 the positions in the circle, starting from an arbitrary position and going around clockwise. Initially each position in the circle is occupied by one person.

The people are going to dance on two kinds of songs: salsa and rumba.

When a salsa is played, the person in position i goes to position j, where j is the number obtained replacing all digits 1 with 2 and all digits 2 with 1 when reading i in base 3 (e.g., the person in position 46 goes to position 65).

When a rumba is played, the person in position i moves to position i+1 (with the identification 3^N = 0).

You are given a string T=T_1T_2\cdots T_{|T|} such that T_i=S if the i-th song is a salsa and T_i=R if it is a rumba.
After all the songs have been played, the person that initially was in position i is in position P_i.
Compute the array P_0,P_1,\dots, P_{3^N-1}.

Constraints

1 \le N \le 12

1 \le |T| \le 200,000

T contains only the characters S and R.

Input

Input is given from Standard Input in the following format:

N
T

Output

You should print on Standard Output:

P_0 P_1 \cdots P_{3^N-1}

Sample Input 1

1
SRS

Sample Output 1

2 0 1

Before any song is played, the positions are: 0, 1, 2.

When we say "person i", we mean "the person that was initially in position i".

After the first salsa, the positions are: 0, 2, 1.

After the rumba, the positions are: 1, 0, 2 (so, person 0 is in position 1, person 1 is in position 0 and person 2 is in position 2).

After the second salsa, the positions are 2, 0, 1 (so, person 0 is in position 2, person 1 is in position 0 and person 2 is in position 1).

Sample Input 2

2
RRSRSSSSR

Sample Output 2

3 8 1 0 5 7 6 2 4

Sample Input 3

3
SRSRRSRRRSRRRR

Sample Output 3

23 9 22 8 3 7 20 24 19 5 18 4 17 12 16 2 6 1 14 0 13 26 21 25 11 15 10

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Linq;

using E = System.Linq.Enumerable;
using System.Numerics;

internal partial class Solver {
    public void Run() {
        var n = ni();
        var t = ns();
        var three = new long[n + 1];
        three[0] = 1;
        for (int i = 1; i < three.Length; i++) {
            three[i] = three[i - 1] * 3;
        }
        var s = new string[n + 1, three[n]];
        s[0, 0] = t;
        var ans = new long[three[n]];
        var builder = new StringBuilder();
        for (int i = 0; i < n; i++) {
            var pattern = three[i + 1];
            for (int j = 0; j < pattern; j++) {
                int bit = (int)(j / three[i]);
                int mod = (int)(j % three[i]);
                var p = s[i, mod];
                builder.Clear();
                for (int k = 0; k < p.Length; k++) {
                    if (p[k] == 'S') {
                        if (k + 1 < p.Length && p[k + 1] == 'S') {
                            // ignore SS
                            k++;
                            continue;
                        }
                        builder.Append('S');
                        if (bit == 1) bit = 2;
                        else if (bit == 2) bit = 1;
                    } else { // R
                        bit++;
                        if (bit == 3) {
                            builder.Append('R');
                            bit = 0;
                        }
                    }
                }
                s[i + 1, j] = builder.ToString();
                for (long k = j; k < ans.Length; k += pattern) {
                    ans[k] += bit * three[i];
                }
            }
        }
        cout.WriteLine(string.Join(" ", ans));
    }
}

// PREWRITEN CODE BEGINS FROM HERE
internal partial class Solver : Scanner {
    public static void Main() {
#if LOCAL
        byte[] inputBuffer = new byte[1000000];
        var inputStream = Console.OpenStandardInput(inputBuffer.Length);
        using (var reader = new StreamReader(inputStream, Console.InputEncoding, false, inputBuffer.Length)) {
            Console.SetIn(reader);
            new Solver(Console.In, Console.Out).Run();
        }
#else
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver(Console.In, Console.Out).Run();
        Console.Out.Flush();
#endif
    }

#pragma warning disable IDE0052
    private readonly TextReader cin;
    private readonly TextWriter cout;
#pragma warning restore IDE0052

    public Solver(TextReader reader, TextWriter writer)
        : base(reader) {
        cin = reader;
        cout = writer;
    }
    public Solver(string input, TextWriter writer)
        : this(new StringReader(input), writer) {
    }

#pragma warning disable IDE1006
#pragma warning disable IDE0051
    private int ni() { return NextInt(); }
    private int[] ni(int n) { return NextIntArray(n); }
    private long nl() { return NextLong(); }
    private long[] nl(int n) { return NextLongArray(n); }
    private double nd() { return NextDouble(); }
    private double[] nd(int n) { return NextDoubleArray(n); }
    private string ns() { return Next(); }
    private string[] ns(int n) { return NextArray(n); }
#pragma warning restore IDE1006
#pragma warning restore IDE0051
}

internal static class LinqPadExtension {
    [Conditional("DEBUG")]
    public static void Dump<T>(this T obj) {
#if DEBUG
        LINQPad.Extensions.Dump(obj);
#endif
    }
}

public class Scanner {
    private readonly TextReader Reader;
    private readonly CultureInfo ci = CultureInfo.InvariantCulture;

    private readonly char[] buffer = new char[2 * 1024];
    private int cursor = 0, length = 0;
    private string Token;
    private readonly StringBuilder sb = new StringBuilder(1024);

    public Scanner()
        : this(Console.In) {
    }

    public Scanner(TextReader reader) {
        Reader = reader;
    }

    public int NextInt() { return checked((int)NextLong()); }
    public long NextLong() {
        var s = Next();
        long r = 0;
        int i = 0;
        bool negative = false;
        if (s[i] == '-') {
            negative = true;
            i++;
        }
        for (; i < s.Length; i++) {
            r = r * 10 + (s[i] - '0');
#if DEBUG
            if (!char.IsDigit(s[i])) throw new FormatException();
#endif
        }
        return negative ? -r : r;
    }
    public double NextDouble() { return double.Parse(Next(), ci); }
    public string[] NextArray(int size) {
        string[] array = new string[size];
        for (int i = 0; i < size; i++) {
            array[i] = Next();
        }

        return array;
    }
    public int[] NextIntArray(int size) {
        int[] array = new int[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextInt();
        }

        return array;
    }

    public long[] NextLongArray(int size) {
        long[] array = new long[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextLong();
        }

        return array;
    }

    public double[] NextDoubleArray(int size) {
        double[] array = new double[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextDouble();
        }

        return array;
    }

    public string Next() {
        if (Token == null) {
            if (!StockToken()) {
                throw new Exception();
            }
        }
        var token = Token;
        Token = null;
        return token;
    }

    public bool HasNext() {
        if (Token != null) {
            return true;
        }

        return StockToken();
    }

    private bool StockToken() {
        while (true) {
            sb.Clear();
            while (true) {
                if (cursor >= length) {
                    cursor = 0;
                    if ((length = Reader.Read(buffer, 0, buffer.Length)) <= 0) {
                        break;
                    }
                }
                var c = buffer[cursor++];
                if (33 <= c && c <= 126) {
                    sb.Append(c);
                } else {
                    if (sb.Length > 0) break;
                }
            }

            if (sb.Length > 0) {
                Token = sb.ToString();
                return true;
            }

            return false;
        }
    }
}