using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("5");
WillReturn.Add("ooxoo");
//5 2 1 3 4
}
else if (InputPattern == "Input2") {
WillReturn.Add("7");
WillReturn.Add("ooooooo");
//7 5 3 1 2 4 6
}
else if (InputPattern == "Input3") {
WillReturn.Add("15");
WillReturn.Add("xooxoxoxoxoxxoo");
//15 11 10 7 6 3 1 2 4 5 8 9 12 13 14
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long[] GetSplitArr(string pStr)
{
return (pStr == "" ? new string[0] : pStr.Split(' ')).Select(pX => long.Parse(pX)).ToArray();
}
static void Main()
{
List<string> InputList = GetInputList();
long N = long.Parse(InputList[0]);
string S = InputList[1];
char[] CharArr = S.ToCharArray();
long UB = CharArr.GetUpperBound(0);
// ImplicitTreapでの区間反転を行う場合、
// 0オリジンでデータを持つ必要があるようです
var InsImplicitTreap = new ImplicitTreap();
for (long I = 1; I <= N; I++) {
InsImplicitTreap.internal_insert(I - 1, I);
}
for (long I = 0; I <= UB; I++) {
if (CharArr[I] == 'o') {
long RangeSta = 0;
long RangeEnd = I;
InsImplicitTreap.internal_reverse(RangeSta, RangeEnd);
}
}
var ValList = InsImplicitTreap.internal_GetValList();
Console.WriteLine(LongEnumJoin(" ", ValList));
}
// セパレータとLong型の列挙を引数として、結合したstringを返す
static string LongEnumJoin(string pSeparater, IEnumerable<long> pEnum)
{
string[] StrArr = Array.ConvertAll(pEnum.ToArray(), pX => pX.ToString());
return string.Join(pSeparater, StrArr);
}
}
#region ImplicitTreap
internal class ImplicitTreap
{
const long INF = long.MaxValue;
static private Random rnd = new Random();
private class Node
{
internal long value;
internal long min;
internal long lazy;
internal long priority;
internal long cnt;
internal bool rev;
internal Node l;
internal Node r;
// コンストラクタ
internal Node(long value, long priority)
{
this.value = value;
this.min = INF;
this.lazy = 0;
this.priority = priority;
this.cnt = 1;
this.rev = false;
this.l = null;
this.r = null;
}
}
Node root = null;
private long private_cnt(Node t)
{
return (t != null) ? t.cnt : 0;
}
private long private_get_min(Node t)
{
return (t != null) ? t.min : INF;
}
private void private_update_cnt(Node t)
{
if ((t != null)) {
t.cnt = 1 + private_cnt(t.l) + private_cnt(t.r);
}
}
private void private_update_min(Node t)
{
if ((t != null)) {
t.min = Math.Min(t.value, Math.Min(private_get_min(t.l), private_get_min(t.r)));
}
}
private void private_pushup(Node t)
{
private_update_cnt(t); private_update_min(t);
}
private void private_pushdown(Node t)
{
if ((t != null) && (t.rev)) {
t.rev = false;
private_swap(ref (t.l), ref (t.r));
if ((t.l) != null) t.l.rev = (t.l.rev == false);
if ((t.r) != null) t.r.rev = (t.r.rev == false);
}
if ((t != null) && (t.lazy != 0)) {
if ((t.l) != null) {
t.l.lazy += t.lazy;
t.l.min += t.lazy;
}
if ((t.r) != null) {
t.r.lazy += t.lazy;
t.r.min += t.lazy;
}
t.value += t.lazy;
t.lazy = 0;
}
private_pushup(t);
}
private void private_split(Node t, long key, ref Node l, ref Node r)
{
if (t == null) {
l = r = null;
return;
}
private_pushdown(t);
long implicit_key = private_cnt(t.l) + 1;
if (key < implicit_key) {
private_split(t.l, key, ref l, ref t.l); r = t;
}
else {
private_split(t.r, key - implicit_key, ref t.r, ref r); l = t;
}
private_pushup(t);
}
private void private_insert(ref Node t, long key, Node item)
{
Node t1 = null;
Node t2 = null;
private_split(t, key, ref t1, ref t2);
private_merge(ref t1, t1, item);
private_merge(ref t, t1, t2);
}
private void private_merge(ref Node t, Node l, Node r)
{
private_pushdown(l);
private_pushdown(r);
if (l == null || r == null) {
t = ((l != null) ? l : r);
}
else if (l.priority > r.priority) {
private_merge(ref l.r, l.r, r); t = l;
}
else {
private_merge(ref r.l, l, r.l); t = r;
}
private_pushup(t);
}
private void private_erase(ref Node t, long key)
{
Node t1 = null, t2 = null, t3 = null;
private_split(t, key + 1, ref t1, ref t2);
private_split(t1, key, ref t1, ref t3);
private_merge(ref t, t1, t2);
}
private void private_add(Node t, long l, long r, long x)
{
Node t1 = null, t2 = null, t3 = null;
private_split(t, l, ref t1, ref t2);
private_split(t2, r - l, ref t2, ref t3);
t2.lazy += x;
t2.min += x;
private_merge(ref t2, t2, t3);
private_merge(ref t, t1, t2);
}
private long private_findmin(Node t, long l, long r)
{
Node t1 = null, t2 = null, t3 = null;
private_split(t, l, ref t1, ref t2);
private_split(t2, r - l, ref t2, ref t3);
long ret = t2.min;
private_merge(ref t2, t2, t3);
private_merge(ref t, t1, t2);
return ret;
}
private void private_reverse(Node t, long l, long r)
{
if (l > r) return;
Node t1 = null, t2 = null, t3 = null;
private_split(t, l, ref t1, ref t2);
private_split(t2, r - l, ref t2, ref t3);
t2.rev = (t2.rev == false);
private_merge(ref t2, t2, t3);
private_merge(ref t, t1, t2);
}
// [l, r)の先頭がmになるように左シフトさせる。std::rotateと同じ仕様
private void private_rotate(Node t, long l, long m, long r)
{
private_reverse(t, l, r);
private_reverse(t, l, l + r - m);
private_reverse(t, l + r - m, r);
}
private void private_dump(Node t)
{
if (t == null) return;
private_pushdown(t);
private_dump(t.l);
Console.Write("{0} ", t.value);
private_dump(t.r);
}
private void private_GetValList(Node t)
{
if (t == null) return;
private_pushdown(t);
private_GetValList(t.l);
mValList.Add(t.value);
private_GetValList(t.r);
}
private void private_swap(ref Node p1, ref Node p2)
{
Node tmp = p1;
p1 = p2;
p2 = tmp;
}
// 指定Indに値を追加
internal void internal_insert(long pos, long x)
{
private_insert(ref root, pos, new Node(x, rnd.Next()));
}
// 閉区間[l,r]に値を加算
internal void internal_add(long l, long r, long x)
{
r++; // 閉区間に変更
private_add(root, l, r, x);
}
// 閉区間[l,r]の最小値を取得
internal long internal_findmin(long l, long r)
{
r++; // 閉区間に変更
return private_findmin(root, l, r);
}
// 指定Indを消す
internal void internal_erase(long pos)
{
private_erase(ref root, pos);
}
// 閉区間[l,r]を反転
internal void internal_reverse(long l, long r)
{
r++; // 閉区間に変更
private_reverse(root, l, r);
}
// [l, r]の先頭がmになるように左シフト。std::rotateと同じ仕様
internal void internal_rotate(long l, long m, long r)
{
r++; // 閉区間に変更
private_rotate(root, l, m, r);
}
// デバッグ表示
internal void internal_dump()
{
private_dump(root);
Console.WriteLine();
}
// 値のListを返す
private List<long> mValList = new List<long>();
internal List<long> internal_GetValList()
{
mValList.Clear();
private_GetValList(root);
return mValList;
}
}
#endregion