#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define pb push_back #define mp make_pair #define rep(i,a,b) for(int i=a;i<=b;i++) #define ren(i,a,b) for(int i=a;i>=b;i--) #define ff first #define ss second #define pll pair #define pii pair #define vll vector #define vii vector #define gi(n) scanf("%d",&n) #define gll(n) scanf("%lld",&n) #define gstr(n) scanf("%s",n) #define gl(n) cin >> n #define oi(n) printf("%d",n) #define oll(n) printf("%lld",n) #define ostr(n) printf("%s",n) #define ol(n) cout << n #define os cout<<" " #define on cout<<"\n" #define o2(a,b) cout< > mat; int n,q,t,l,r; string s; struct node { int c[26]={0},l=0; }tree[600005]; int res[26]={0}; void build(int lo,int hi,int i) { if(lo==hi) { tree[i].l=0,tree[i].c[s[lo]-'a']=1; return; } int mid=(lo+hi)/2; build(lo,mid,2*i); build(mid+1,hi,2*i+1); rep(j,0,25) tree[i].c[j]=tree[2*i].c[j]+tree[2*i+1].c[j]; } void update(int left,int right,int i) { if(tree[i].l!=0) { int c1[26]={0}; rep(j,0,25) c1[j]=tree[i].c[j]; rep(j,0,25) tree[i].c[j]=c1[((j-tree[i].l)%26+26)%26]; if(left!=right) { tree[2*i].l+=tree[i].l; tree[2*i+1].l+=tree[i].l; tree[2*i].l%=26; tree[2*i+1].l%=26; } tree[i].l=0; } if(left>r||rightright) return; if(left>=l&&right<=r) { tree[i].l+=t; tree[i].l%=26; if(tree[i].l!=0) { int c1[26]={0}; rep(j,0,25) c1[j]=tree[i].c[j]; rep(j,0,25) tree[i].c[j]=c1[((j-tree[i].l)%26+26)%26]; if(left!=right) { tree[2*i].l+=tree[i].l; tree[2*i+1].l+=tree[i].l; tree[2*i].l%=26; tree[2*i+1].l%=26; } tree[i].l=0; } return; } update(left,(left+right)/2,2*i); update((left+right)/2+1,right,2*i+1); rep(j,0,25)tree[i].c[j]=tree[2*i].c[j]+tree[2*i+1].c[j]; } void query(int left,int right,int i) { //o2(left,right);os;ol(i);on; if(tree[i].l!=0) { int c1[26]={0}; rep(j,0,25) c1[j]=tree[i].c[j]; rep(j,0,25) tree[i].c[j]=c1[((j-tree[i].l)%26+26)%26]; if(left!=right) { tree[2*i].l+=tree[i].l; tree[2*i+1].l+=tree[i].l; tree[2*i].l%=26; tree[2*i+1].l%=26; } tree[i].l=0; } if(left>r||rightright) return; if(right<=r&&left>=l) { //o2(i,tree[i].c[0]);on; rep(j,0,25) res[j]+=tree[i].c[j]; return; } query(left,(left+right)/2,2*i); query((left+right)/2+1,right,2*i+1); } ll pp[100005],m=1e9+7; int main() {ios_base::sync_with_stdio(false); cin>>n>>q; cin>>s; build(0,n-1,1); pp[0]=1; rep(i,1,100004) pp[i]=(pp[i-1]*1ll*2)%m; while(q--) { int qno; cin>>qno; if(qno==1) { cin>>l>>r>>t; update(0,n-1,1); } else { cin>>l>>r; rep(i,0,25)res[i]=0; query(0,n-1,1); ll cc=0; ll ans=1; rep(j,0,25) { if(res[j]>0) { cc++; ans=(ans*pp[res[j]-1])%m; } } //ol(cc);on; ans=(ans*(cc+1))%m; ans=(ans-1)%m; if(ans<0)ans+=m; ol(ans);on; } } return 0; }