#include<bits/stdc++.h>
#define int long long
using namespace std;
char val[200001];
int tmp[31];
struct Tree{
int l;
int r;
int lazy;
int num[31];
}tree[800001];
void pushup(int k)
{
for(int i = 1;i <= 26;++ i)
{
tree[k].num[i] = tree[k << 1].num[i] + tree[k << 1 | 1].num[i];
}
return;
}
void pushdown(int k)
{
tree[k << 1].lazy = tree[k].lazy;
tree[k << 1 | 1].lazy = tree[k].lazy;
memset(tree[k << 1].num , 0 , sizeof tree[k << 1].num);
memset(tree[k << 1 | 1].num , 0 , sizeof tree[k << 1 | 1].num);
tree[k << 1].num[tree[k].lazy] = tree[k << 1].r - tree[k << 1].l + 1;
tree[k << 1 | 1].num[tree[k].lazy] = tree[k << 1 | 1].r - tree[k << 1 | 1].l + 1;
tree[k].lazy = 0;
return;
}
void build(int l , int r , int k)
{
tree[k].l = l;
tree[k].r = r;
tree[k].lazy = 0;
memset(tree[k].num , 0 , sizeof tree[k].num);
if(l == r)
{
++ tree[k].num[val[l] - 'a' + 1];
return;
}
int mid = l + (r - l) / 2;
build(l , mid , k << 1);
build(mid + 1 , r , k << 1 | 1);
pushup(k);
return;
}
int query(int l , int r , int k , int c)
{
if(l <= tree[k].l && tree[k].r <= r)
{
return tree[k].num[c];
}
if(tree[k].lazy != 0)
pushdown(k);
int mid = tree[k].l + (tree[k].r - tree[k].l) / 2 , res = 0;
if(l <= mid)
{
res += query(l , r , k << 1 , c);
}
if(r > mid)
{
res += query(l , r , k << 1 | 1 , c);
}
return res;
}
void change(int l , int r , int k , int c)
{
if(l <= tree[k].l && tree[k].r <= r)
{
memset(tree[k].num , 0 , sizeof tree[k].num);
tree[k].num[c] = tree[k].r - tree[k].l + 1;
tree[k].lazy = c;
return;
}
if(tree[k].lazy != 0)
pushdown(k);
int mid = tree[k].l + (tree[k].r - tree[k].l) / 2;
if(l <= mid)
{
change(l , r , k << 1 , c);
}
if(r > mid)
{
change(l , r , k << 1 | 1 , c);
}
pushup(k);
return;
}
void query_sort(int l , int r)
{
memset(tmp , 0 , sizeof tmp);
for(int i = 1;i <= 26;++ i)
{
tmp[i] = query(l , r , 1 , i);
}
int last = 0;
for(int i = 1;i <= 26;++ i)
{
if(tmp[i] == 0)
{
continue;
}
change(last + 1 , last + tmp[i], 1 , i);
last = last + tmp[i];
}
return;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n = 0,m = 0;
cin >> n >> m;
for(int i = 1;i <= n;++ i)
{
char tmp;
cin >> tmp;
if(tmp >= 'A' && tmp <= 'Z')
{
tmp += 32;
}
val[i] = tmp;
}
build(1 , n , 1);
for(int i = 1;i <= m;++ i)
{
int opt = 0 , x = 0 , y = 0;
char k;
cin >> opt;
switch (opt)
{
case 1:{
cin >> x >> y;
cin >> k;
if(k >= 'A' && k <= 'Z')
{
k += 32;
}
cout << query(x , y , 1 , k - 'a' + 1) << endl;
break;
}
case 2:{
cin >> x >> y;
cin >> k;
if(k >= 'A' && k <= 'Z')
{
k += 32;
}
change(x , y , 1 , k - 'a' + 1);
break;
}
default:{
cin >> x >> y;
query_sort(x , y);
break;
}
}
}
return 0;
}