#include <bits/stdc++.h>
using namespace std;
template <typename FUNC>
struct ReturnType;
template <typename RT, typename... AT>
struct ReturnType<RT (*)(AT...)> {
  using type = RT;
};
template <typename FUNC>
struct SecondArgType;
template <typename RT, typename A1T, typename A2T, typename... AT>
struct SecondArgType<RT (*)(A1T, A2T, AT...)> {
  using type = A2T;
};
template <typename OPS>
class SegTree {
 public:
  using T = typename ReturnType<decltype(&OPS::combine)>::type;
  using UPD = typename SecondArgType<decltype(&OPS::update)>::type;
  SegTree(int n) : data(4 * n), n(n) {}
  SegTree(const vector<T> &a) : SegTree(a.size()) { doBld(a, 1, 0, n - 1); }
  T get(int l, int r) { return doGet(l, r, 1, 0, n - 1); }
  void upd(int i, UPD val) { doUpd(i, val, 1, 0, n - 1); }

 private:
  int n;
  vector<T> data;
  void doBld(const vector<T> &a, int v, int from, int to) {
    if (from == to) {
      data[v] = a[from];
    } else {
      int mid = (from + to) / 2;
      doBld(a, 2 * v, from, mid);
      doBld(a, 2 * v + 1, mid + 1, to);
      doRecalc(v);
    }
  }
  void doUpd(int i, UPD val, int v, int from, int to) {
    if (from < to) {
      int mid = (from + to) / 2;
      if (i <= mid) {
        doUpd(i, val, 2 * v, from, mid);
      } else {
        doUpd(i, val, 2 * v + 1, mid + 1, to);
      }
      doRecalc(v);
    } else {
      data[v] = OPS::update(data[v], val);
    }
  }
  T doGet(int l, int r, int v, int from, int to) {
    if (l <= from && to <= r) {
      return data[v];
    }
    int mid = (from + to) / 2;
    if (l > mid) {
      return doGet(l, r, 2 * v + 1, mid + 1, to);
    }
    if (mid + 1 > r) {
      return doGet(l, r, 2 * v, from, mid);
    }
    return OPS::combine(doGet(l, r, 2 * v, from, mid),
                        doGet(l, r, 2 * v + 1, mid + 1, to));
  }
  void doRecalc(int v) { data[v] = OPS::combine(data[2 * v], data[2 * v + 1]); }
};
struct SegTreeOps {
  static int combine(int a, int b) { return a + b; }
  static int update(int cur, int val) { return val; }
};
struct State {
  int n;
  SegTree<SegTreeOps> st;
  set<int> pos, neg;
  char chPos, chNeg;
  State(int n, char chPos, char chNeg)
      : n(n), st(n), chPos(chPos), chNeg(chNeg) {}
  int updCh(int i, char ch) {
    int val = 0;
    if (ch == chPos) {
      val = 1;
    } else if (ch == chNeg) {
      val = -1;
    }
    return upd(i, val);
  }
  int upd(int i, int val) {
    if (pos.count(i) > 0) {
      pos.erase(i);
    } else if (neg.count(i) > 0) {
      neg.erase(i);
    } else {
      st.upd(i, 0);
    }
    if (val == 1) {
      pos.insert(i);
    } else if (val == -1) {
      neg.insert(i);
    } else {
      st.upd(i, 1);
    }
    return calcRes();
  }
  int calcRes() {
    int tot = st.get(0, n - 1);
    if (neg.size() == 0) {
      return tot;
    }
    if (pos.size() == 0) {
      return 0;
    }
    int ans = tot;
    int leftPos = *pos.begin(), leftNeg = *neg.begin();
    if (leftNeg < leftPos) {
      ans -= st.get(leftNeg, leftPos);
    }
    int rightPos = *pos.rbegin(), rightNeg = *neg.rbegin();
    if (rightPos < rightNeg) {
      ans -= st.get(rightPos, rightNeg);
    }
    return ans;
  }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  string s;
  cin >> n >> m >> s;
  vector<State> all;
  all.emplace_back(n, 'P', 'R');
  all.emplace_back(n, 'S', 'P');
  all.emplace_back(n, 'R', 'S');
  int start = 0;
  for (int i = 0; i < n; i++) {
    for (auto &st : all) {
      int v = st.updCh(i, s[i]);
      if (i == n - 1) {
        start += v;
      }
    }
  }
  cout << start << "\n";
  for (int i = 0; i < m; i++) {
    int j;
    char ch;
    cin >> j >> ch;
    j--;
    int res = 0;
    for (auto &st : all) {
      res += st.updCh(j, ch);
    }
    cout << res << "\n";
  }
}
