#include<stdio.h>
#define N 100009
#include<set>
#define IT std::set < node > :: iterator
#include<iostream>
#define cin std::cin
struct node
{
int l, r;
mutable char val;
node(int L, int R = -1, char VAL = 0) : l(L), r(R), val(VAL){}
inline bool operator < (const node& a)const
{
return l < a.l;
}
};
std::set < node > s;
inline IT split(int pos)
{
IT it = s.lower_bound(node(pos));
if (it != s.end() && it -> l == pos)
return it;
it --;
int l = it -> l, r = it -> r;
char val = it -> val;
s.erase(it);
s.insert(node(l, pos - 1, val));
return s.insert(node(pos, r, val)).first;
}
inline void bulldoze(int l, int r, char val)
{
IT itr = split(r + 1), itl = split(l);
s.erase(itl, itr);
s.insert(node(l, r, val));
}
inline int query(int l, int r, char val)
{
IT itr = split(r + 1), itl = split(l);
int ret = 0;
while (itl != itr)
{
if (itl -> val == val)
ret += (itl -> r - itl -> l + 1);
itl ++;
}
return ret;
}
inline void Sort(int l, int r)
{
int cnt[39];
for (int i = 0;i < 28;i ++)
cnt[i] = 0;
IT itr = split(r + 1), itl = split(l), tmp = itl;
while (itl != itr)
cnt[itl -> val - 'A'] += itl -> r - itl -> l + 1, itl ++;
s.erase(tmp, itr);
int cur = l;
for(int i = 0;i < 26;i ++)
if (cnt[i])
s.insert(node(cur, cur + cnt[i] - 1, i + 'A')), cur += cnt[i];
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
char ch;
for (int i = 1;i <= n;i ++)
{
cin >> ch;
if (ch >= 'a')
ch = ch - 'a' + 'A';
s.insert(node(i, i, ch));
}
int opt, l, r;
while (m --)
{
scanf("%d%d%d", &opt, &l, &r);
if (opt != 3)
{
cin >> ch;
if (ch >= 'a')
ch = ch - 'a' + 'A';
}
if (opt == 1)
printf("%d\n", query(l, r, ch));
if (opt == 2)
bulldoze(l, r, ch);
if (opt == 3)
Sort(l, r);
}
return 0;
}