#include<bits/stdc++.h>
using namespace std;

using ULL = unsigned long long;
const ULL B = 100'000'007;

class SegmentTree {
 public:
  SegmentTree(int n) : size_(1), pow_(1, 1) {
    while(size_ < n) size_ <<= 1;
    node_.assign(size_ << 1, 0);
    lazy_.assign(size_ << 1, 0);
    awaiting_.assign(size_ << 1, false);
    while(pow_.size() <= size_) pow_.emplace_back(pow_.back() * B);
  }
  ULL find(int left, int right) {return find(left, right + 1, 1, 0, size_).value;}
  void update(int left, int right, ULL value) {update(left, right + 1, value, 1, 0, size_);}
 private:
  struct Node {ULL value; int length;};
  inline int left_child(int node) const {return node << 1;}
  inline int right_child(int node) const {return (node << 1) + 1;}
  inline ULL merge(ULL vl, ULL vr, int l) const {return vl * pow_.at(l) + vr;}
  inline Node merge(Node& l, Node& r) const {return {l.value * pow_.at(r.length) + r.value, l.length + r.length};}
  inline ULL hash(ULL v, int l) const {
    using Memo = pair<ULL, int>;
    static map<Memo, ULL> memo;
    auto m = Memo(v, l);
    if(memo.count(m)) return memo.at(m);
    ULL res = v;
    for(auto i = 1; i < l; ++i) res = res * B + v;
    memo.insert(make_pair(m, res));
    return res;
  }
  inline void propagate(int k, int l, int r) {
    if(awaiting_.at(k)) {
      if(k < size_) lazy_.at(left_child(k)) = lazy_.at(right_child(k)) = lazy_.at(k);
      if(k < size_) awaiting_.at(left_child(k)) = awaiting_.at(right_child(k)) = true;
      node_.at(k) = hash(lazy_.at(k), r - l);
      lazy_.at(k) = 0;
      awaiting_.at(k) = false;
    }
  }
  Node find(int a, int b, int k, int l, int r) {
    propagate(k, l, r);
    if(b <= l || r <= a) return {0, 0};
    if(a <= l && r <= b) return {node_.at(k) , r - l};
    auto vl = find(a, b, left_child(k), l, (l + r) / 2);
    auto vr = find(a, b, right_child(k), (l + r) / 2, r);
    return merge(vl, vr);
  }
  ULL update(int a, int b, ULL value, int k, int l, int r) {
    propagate(k, l, r);
    if(b <= l || r <= a) return node_.at(k);
    if(a <= l && r <= b) {lazy_.at(k) = value; awaiting_.at(k) = true; propagate(k, l, r); return node_.at(k);}
    auto vl = update(a, b, value, left_child(k), l, (l + r) / 2);
    auto vr = update(a, b, value, right_child(k), (l + r) / 2, r);
    return node_.at(k) = merge(vl, vr, (r - l) / 2);
  }
  int size_;
  vector<ULL> node_;
  vector<ULL> lazy_;
  vector<bool> awaiting_;
  vector<ULL> pow_;
 public:
  void traverse() {traverse(1,0,size_);}
  void traverse(int k, int l, int r, int d=0) {
    propagate(k, l, r);
    if(k < size_) {
      traverse(right_child(k),(l+r)/2,r,d+1);
      for(auto i=0;i<d;++i)cout<<"    ";
      cout<<node_.at(k)<<endl;
      traverse(left_child(k),l,(l+r)/2,d+1);
    } else {
      for(auto i=0;i<d;++i)cout<<"    ";
      cout<<node_.at(k)<<endl;
    }
  }
};

string compare(auto& t, int a, int b, int c, int d) {
  if(t.find(a, b) == t.find(c, d)) return "e";
  int low = -1, high = min(b - a, d - c) + 1;
  while(low + 1 != high) {
    auto middle = (low + high) / 2;
    if(t.find(a, a + middle) == t.find(c, c + middle)) low = middle;
    else high = middle;
  }
  if(low == b - a) return "s";
  if(low == d - c) return "t";
  return t.find(a + high, a + high) < t.find(c + high, c + high) ? "s" : "t";
}

int main() {
  int N;
  string U;
  int Q;
  cin >> N >> U >> Q;

  SegmentTree segtree(N);
  for(auto i = 0; i < N; ++i) segtree.update(i, i, U[i]);
//   segtree.traverse();

  for(auto i = 0; i < Q; ++i) {
    string s;
    cin >> s;
    if(s == "set") {
      int x, y; char z;
      cin >> x >> y >> z;
      --x; --y;
      segtree.update(x, y, z);
    } else {
      int a, b, c, d;
      cin >> a >> b >> c >> d;
      --a; --b; --c; --d;
      cout << compare(segtree, a, b, c, d) << endl;
    }
  }
}

Measured memory_bytes: 15528