import std.algorithm;
import std.array;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.random;

struct ImplicitKeyTreapNode(Value, Extra=void) {
  enum has_extra = !(is (Extra == void));
  ImplicitKeyTreapNode!(Value, Extra)* left, right;
  Value value;
  static if (has_extra) Extra extra;
  int y;
  int sz;
  this (Value _value) {
    value = _value;
    y = uniform!int;
    sz = 1;
  }
}

final class ImplicitKeyTreap(Value, Extra=void, alias relax_op="", alias push_op="", alias update_op="") {
  /*
  enum has_push = isCallable!push_op;
  enum has_relax = isCallable!relax_op;
  enum has_update = isCallable!update_op;
  */
  enum has_push = true;
  enum has_relax = true;
  enum has_update = true; 
  static assert (has_push == has_update);
  alias Node = ImplicitKeyTreapNode!(Value, Extra);
  Node *root;

  private static int _size (const Node *t) {
    return t ? t.sz : 0;
  }

  private static void _relax_inc (Node *t) {
    ++t.sz;
    static if (has_relax) relax_op (t);
  }

  private static void _relax_dec (Node *t) {
    --t.sz;
    static if (has_relax) relax_op (t);
  }

  private static void _relax (Node *t) {
    t.sz = 1;
    if (t.left) t.sz += t.left.sz;
    if (t.right) t.sz += t.right.sz;
    static if (has_relax) relax_op (t);
  }

  private static void _split (Node *t, ref Node *l, ref Node *r, int key) {
    if (!t) {
      l = r = null;
      return;
    }
    static if (has_push) push_op (t);
    int ls;
    if (t.left) ls = t.left.sz;
    if (key <= ls) {
      _split (t.left, l, t.left, key);
      r = t;
    } else {
      _split (t.right, t.right, r, key - ls - 1);
      l = t;
    }
    _relax (t);
  }

  private static void _build (ref Node *t, Value[] v) {
    if (v.length == 1) {
      t = new Node (v[0]);
      static if (has_relax) relax_op (t);
    } else {
      immutable m = v.length >> 1;
      Node* tl, tr;
      _build (tl, v[0 .. m]);
      _build (tr, v[m .. $]);
      _merge (t, tl, tr);
    }
  }

  private static void _insert (ref Node *t, Node *p, int pos) {
	if (!t) {
      static if (has_relax) relax_op (p);
	  t = p;
      return;
    } else if (p.y >= t.y) {
      _split (t, p.left, p.right, pos);
      t = p;
      _relax (t);
    } else {
      static if (has_push) if (t) push_op (t);
      int ls;
      if (t.left) ls = t.left.sz;
      if (pos <= ls) {
        _insert (t.left, p, pos);
        _relax_inc (t);
      } else {
        _insert (t.right, p, pos - ls - 1);
        _relax_inc (t);
      }
    }
  }

  private static void _merge (ref Node *t, Node *l, Node *r) {
    if (!l) {
      static if (has_push) if (r) push_op (r);
      t = r;
    } else if (!r) {
      static if (has_push) push_op (l);
      t = l;
    } else {
      static if (has_push) {
        push_op (l);
        push_op (r);
      }
      if (l.y > r.y) {
        _merge (l.right, l.right, r);
        _relax (l);
        t = l;
      } else {
        _merge (r.left, l, r.left);
        _relax (r);
        t = r;
      }
    }
  }

  private static _replace (Node *t, int pos, Value value) {
    static if (has_relax) {
      Node*[128] path = void;
      int n;
    }
    while (true) {
      static if (has_push) push_op (t);
      static if (has_relax) {
        path[n++] = t;
      }
      int ls;
      if (t.left) ls = t.left.sz;
      if (pos == ls) {
        t.value = value;
        break;
      }
      if (pos < ls) {
        t = t.left;
      } else {
        t = t.right;
        pos -= ls + 1;
      }
    }
    static if (has_relax) {
      foreach_reverse (i; 0 .. n) {
        relax_op (path[i]);
      }
    }
  }

  private static inout(Node*) _get (inout(Node*) t, int pos) in {
    assert (pos >= 0);
    assert (pos < _size (t));
    assert (t);
  } body {
    if (t.left) {
      if (pos < t.left.sz) {
        return _get (t.left, pos);
      }
      pos -= t.left.sz;
    }
    if (!pos) {
      return t;
    }
    return _get (t.right, pos - 1);
  }

  private static void _remove (ref Node *t, int pos) in {
    assert (t);
    assert (pos >= 0);
    assert (pos < _size (t));
  } body {
    static if (has_push) push_op (t);
    int ls;
    if (t.left) ls = t.left.sz;
    if (pos == ls) {
      _merge (t, t.left, t.right);
    } else if (pos < ls) {
      _remove (t.left, pos);
      assert (t);
      _relax_dec (t);
    } else {
      _remove (t.right, pos - ls - 1);
      assert (t);
      _relax_dec (t);
    }
  }

  void insert (int pos, Value value) {
    _insert (root, new Node (value), pos);
  }

  void remove (int pos) {
    _remove (root, pos);
  }

  void replace (int pos, Value value) {
    _replace (root, pos, value);
  }

  Value get (int pos) const in {
    assert (pos < size ());
  } body {
    return _get (root, pos).value;
  }

  int size () const {
    return _size (root);
  }

  Node*[] getNodes () {
    Node*[] a;
    a.reserve (_size (root));
    void rec (Node *t) {
      if (t.left) rec (t.left);
      a ~= t;
      if (t.right) rec (t.right);
    }
    rec (root);
    return a;
  }

  Value[] getValues () {
    Value[] a;
    a.reserve (_size (root));
    void rec (Node *t) {
      static if (has_push) push_op (t);
      if (t.left) rec (t.left);
      a ~= t.value;
      if (t.right) rec (t.right);
    }
    if (root) rec (root);
    return a;
  }

  static if (has_relax) {
    private Node[256] nodes;
    private int cur;

    private void persistent_split (Node *t, ref Node *l, ref Node *r, int key) {
      if (!t) {
        l = r = null;
        return;
      }
      int ls;
      if (t.left) ls = t.left.sz;
      Node *q = &nodes[cur++];
      q.value = t.value;
      q.y = t.y;
      if (key <= ls) {
        q.right = t.right;
        persistent_split (t.left, l, q.left, key);
        r = q;
      } else {
        q.left = t.left;
        persistent_split (t.right, q.right, r, key - ls - 1);
        l = q;
      }
      _relax (q);
    }
    Extra reduce (int l, int r) {
      cur = 0;
      Node *t1, t2, t3;
      persistent_split (root, t1, t2, l);
      persistent_split (t2, t2, t3, r - l);
      return t2.extra;
    }
  }

  static if (has_update) {
    void update (int l, int r) {
      if (!l) {
        Node *t1, t2;
        _split (root, t1, t2, r);
        update_op (t1);
        _merge (root, t1, t2);
      } else {
        Node *t1, t2, t3;
        _split (root, t1, t2, l);
        _split (t2, t2, t3, r - l);
        update_op (t2);
        _merge (t2, t2, t3);
        _merge (root, t1, t2);
      }
    }
  }
  this (Value[] v) {
    _build (root, v);
  }
}

struct E {
  //ImplicitKeyTreapNode!(char, E) *parent;
  bool rev;
}

void relax (ImplicitKeyTreapNode!(char, E)  *t) {
  //if (t.left) t.left.extra.parent = t;
  //if (t.right) t.right.extra.parent = t;
}

void push (ImplicitKeyTreapNode!(char, E)  *t) {
  if (t.extra.rev) {
    t.extra.rev = false;
    swap (t.left, t.right);
    if (t.left) t.left.extra.rev = !t.left.extra.rev;
    if (t.right) t.right.extra.rev = !t.right.extra.rev;
  }
}

void update (ImplicitKeyTreapNode!(char, E)  *t) {
  t.extra.rev = !t.extra.rev;
}

void main() {
  rndGen.seed (1);
  auto s = readln.stripRight;
  auto z = readln.stripRight;
  const int nt = z.to!int;
  auto tree = new ImplicitKeyTreap!(char, E, relax, push, update) (s.dup);
  int n = s.length.to!int;
  foreach (tid; 0 .. nt) {
    z = readln.stripRight;
    auto w = z.splitter;
    const int t = w.front.to!int;
    w.popFront ();
    if (t == 1) {
      //tree.update (0, n);
      update (tree.root);
    } else {
      int f = w.front.to!int;
      w.popFront ();
      char c = w.front[0]; 
      tree.insert (f == 1 ? 0 : n, c);
      ++n;
    }
    debug {
      auto ans = tree.getValues ();
      stderr.writeln (ans);
    }
  }
  /*
  auto w = tree.reduce (0, n);
  foreach (i; 0 .. n) {
    write (tree.get (i));
  }
  writeln;
  */
  auto ans = tree.getValues ();
  writeln (ans);
}

