#include using namespace std; typedef pair ii; typedef pair pii; typedef vector vi; typedef vector vii; typedef vector vpii; typedef long long int ll; typedef unsigned long long int ull; #define mi 1000000007 #define rep(i,a,b) for(i=a;i=a;i--) #define inf INT_MAX #define gc getchar_unlocked #define PB push_back #define MP make_pair #define fi first #define se second #define SET(a,b) memset(a,b,sizeof(a)) #define MAX 500005 #define gu getchar #define pu putchar #define si(n) scanf("%d",&n) #define dout(n) printf("%d\n",n) #define sll(n) scanf("%lld",&n) #define lldout(n) printf("%lld\n",n) #define TRACE #ifdef TRACE #define trace1(x) cerr << #x << ": " << x << endl; #define trace2(x, y) cerr << #x << ": " << x << " | " << #y << ": " << y << endl; #define trace3(x, y, z) cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl; #define trace4(a, b, c, d) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl; #define trace5(a, b, c, d, e) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << endl; #define trace6(a, b, c, d, e, f) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << " | " << #f << ": " << f << endl; #else #define trace1(x) #define trace2(x, y) #define trace3(x, y, z) #define trace4(a, b, c, d) #define trace5(a, b, c, d, e) #define trace6(a, b, c, d, e, f) #endif int gcd(int a,int b) { return b==0 ? a : gcd (b,a%b);} int lcm(int a,int b) { return a*(b/gcd(a,b));} ll pow1(ll a,ll b) { ll ans=1; while(b>0) { if(b&1) ans=(ans*a)%mi; a=(a*a)%mi; b>>=1; } return ans; } struct node { ll arr[26]; ll cnt; }tree[400005]; ll a[100005]; void build(int low,int high,int pos) { int i; if(low==high) { tree[pos].arr[a[low]]=1; rep(i,0,26) if(i!=a[low]) tree[pos].arr[i]=0; tree[pos].cnt=0; return; } int mid=(low+high)>>1; build(low,mid,2*pos+1); build(mid+1,high,2*pos+2); rep(i,0,26) tree[pos].arr[i]=tree[2*pos+1].arr[i]+tree[2*pos+2].arr[i]; tree[pos].cnt=0; } void split(int i) { ll j; tree[2*i+1].cnt=tree[2*i+1].cnt+tree[i].cnt; tree[2*i+2].cnt=tree[2*i+2].cnt+tree[i].cnt; ll inc=tree[i].cnt; ll temp1[26],temp2[26]; rep(j,0,26) { temp1[(j+inc)%26]=tree[2*i+1].arr[j]; temp2[(j+inc)%26]=tree[2*i+2].arr[j]; } rep(j,0,26) { tree[2*i+1].arr[j]=temp1[j]; tree[2*i+2].arr[j]=temp2[j]; } tree[i].cnt=0; } void merge(int i) { int j; rep(j,0,26) tree[i].arr[j]=tree[2*i+1].arr[j]+tree[2*i+2].arr[j]; } node merge1(node x,node y) { ll i; node m; rep(i,0,26) m.arr[i]=x.arr[i]+y.arr[i]; m.cnt=0; return m; } node query(int low,int high,int pos,int l,int r) { int i; node k; rep(i,0,26) k.arr[i]=0,k.cnt=0; if(low>r || high=high) return tree[pos]; split(pos); int mid=(low+high)>>1; node left=query(low,mid,2*pos+1,l,r),righta=query(mid+1,high,2*pos+2,l,r); node ans=merge1(left,righta); merge(pos); return ans; } void update(int low,int high,int pos,int l,int r,ll val) { if(high>1; update(low,mid,2*pos+1,l,r,val); update(mid+1,high,2*pos+2,l,r,val); merge(pos); } int main() { int i,j,n,m; string s; si(n); si(m); cin>>s; rep(i,0,n) a[i]=(int)(s[i]-'a'); build(0,n-1,0); int ch,l,r; ll x; while(m--) { si(ch); si(l); si(r); if(ch==2) { ll ans=0; node m1=query(0,n-1,0,l,r); vector v1; rep(i,0,26) if(m1.arr[i]) v1.PB(m1.arr[i]); ll tot=0,sz=(ll)v1.size(); rep(i,0,v1.size()) tot+=v1[i]; ans=pow1(2,tot-sz); ans=(ans*(sz+1))%mi; ans=(ans-1+mi)%mi; lldout(ans); } else { ll t; sll(t); update(0,n-1,0,l,r,t); } } return 0; }