#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, q;
set<int> s[63];
char str[N];
int tree[N];
inline void update(int idx, int val) {
  while (idx < N) {
    tree[idx] += val;
    idx += idx & -idx;
  }
}
int query(int idx) {
  int sm = 0;
  while (idx > 0) {
    sm += tree[idx];
    idx -= idx & -idx;
  }
  return sm;
}
int get(int sum) {
  int low = 1;
  int high = n;
  int ans = 0;
  while (low <= high) {
    int mid = (low + high) / 2;
    if (query(mid) >= sum) {
      ans = mid;
      high = mid - 1;
    } else {
      low = mid + 1;
    }
  }
  return ans;
}
int main() {
  cin >> n >> q;
  scanf("%s", str + 1);
  map<char, int> m;
  int cnt = 0;
  for (char i = 'a'; i <= 'z'; i++) {
    m[i] = ++cnt;
  }
  for (char i = 'A'; i <= 'Z'; i++) {
    m[i] = ++cnt;
  }
  for (char i = '0'; i <= '9'; i++) {
    m[i] = ++cnt;
  }
  for (int i = 1; i <= n; i++) {
    int pos = m[str[i]];
    s[pos].insert(i);
  }
  for (int i = 1; i <= n; i++) {
    update(i, 1);
  }
  while (q--) {
    int x, y;
    scanf("%d%d", &x, &y);
    char ch[2];
    scanf("%s", ch);
    x = get(x);
    y = get(y);
    int pos = m[ch[0]];
    auto it1 = s[pos].lower_bound(x);
    auto it2 = s[pos].upper_bound(y);
    if (it1 == it2) {
      continue;
    }
    vector<int> todel;
    todel.clear();
    auto it = s[pos].upper_bound(x);
    if (s[pos].find(x) != s[pos].end()) {
      it--;
    }
    while (it != s[pos].end()) {
      if (*it > y) break;
      todel.push_back(*it);
      ++it;
    }
    for (auto val : todel) {
      s[pos].erase(val);
      update(val, -1);
    }
  }
  for (int i = 1; i <= n; i++) {
    if (query(i) - query(i - 1)) {
      printf("%c", str[i]);
    }
  }
  cout << endl;
}
