qwq
#include<bits/stdc++.h>
using namespace std;
#define IT set<node>::iterator
struct node{
unsigned l,r;
char v;
node(unsigned LEFT,unsigned RIGNT=0,char VALUE=0);
};
node::node(unsigned LEFT,unsigned RIGHT,char VALUE){
l=LEFT;
r=RIGHT;
v=VALUE;
}
bool operator<(node a,node b){
return a.l<b.l;
}
set<node>odt;
unsigned n,m;
inline IT split(unsigned p){
IT it=odt.lower_bound(node(p));
if(it!=odt.end()&&it->l==p)return it;
--it;
unsigned r=it->r,l=it->l;
char v=it->v;
odt.erase(it);
odt.insert(node(l,p-1,v));
return odt.insert(node(p,r,v)).first;
}
inline void assign(unsigned l,unsigned r,int v){
IT itr=split(r+1),itl=split(l);
odt.erase(itl,itr);
odt.insert(node(l,r,v));
}
inline unsigned getcnt(unsigned l,unsigned r,char v){
IT itr=split(r+1),itl=split(l);
unsigned cnt=0;
for(IT it=itl;it!=itr;++it)
if(it->v==v)
cnt+=it->r-it->l+1;
return cnt;
}
inline void sortsec(unsigned l,unsigned r){
IT itr=split(r+1),itl=split(l);
unsigned cnt[26]={0};
for(IT it=itl;it!=itr;++it)
cnt[it->v-'A']+=it->r-it->l+1;
for(register unsigned i=0;i<26;++i){
odt.insert(node(l,l+cnt[i],i+'A'));
l+=cnt[i];
}
}
int main(){
scanf("%d%d",&n,&m);
for(register unsigned i=1;i<=n;i++){
char tmp;
cin>>tmp;
if(tmp>='a'&&tmp<='z')tmp-='a'-'A';
odt.insert(node(i,i,tmp));
}
odt.insert(node(n+1,n+1,'\0'));
for(register unsigned i=1;i<=m;i++){
int t,l,r;
char c;
scanf("%d%d%d",&t,&l,&r);
if(t==1||t==2)
scanf("%c",c);
if(t==1)
printf("%u\n",getcnt(l,r,c));
if(t==2)
assign(l,r,c);
if(t==3)
sortsec(l,r);
}
return 0;
}