#include #define left (2*i+1) #define right (2*i+2) #define mid ((l+r)>>1) #define M 1000000007 using namespace std; int n,m; string s; int seg[26][1000001],lazy[1000000],qr[26]; long long int pw[1000000]; int clear_lazy(int i){ int temp[26]; for (int j=0;j<26;j++) temp[(j+lazy[i])%26] = seg[j][i]; for (int j=0;j<26;j++) seg[j][i] = temp[j]; lazy[left] = (lazy[left]+lazy[i])%26; lazy[right] = (lazy[right]+lazy[i])%26; lazy[i] = 0; return 0; } int update(int i,int l,int r,int x,int y,int t){ if (lazy[i]) clear_lazy(i); if (l>r || x>r || y=x && r<=y){ lazy[i]+=t; lazy[i]%=26; clear_lazy(i); return 0; } update(left,l,mid,x,y,t); update(right,mid+1,r,x,y,t); for (int j=0;j<26;j++) seg[j][i] = seg[j][left]+seg[j][right]; return 0; } int construct(int i,int l,int r){ if (l>r) return 0; if (l==r){ seg[s[l]-'a'][i] = 1; return 0; } construct(left,l,mid); construct(right,mid+1,r); for (int j=0;j<26;j++) seg[j][i] = seg[j][left]+seg[j][right]; return 0; } int query(int i,int l,int r,int x,int y){ if (lazy[i]) clear_lazy(i); if (l>r || x>r || y=x && r<=y){ for (int j=0;j<26;j++) qr[j]+=seg[j][i]; return 0; } query(left,l,mid,x,y); query(right,mid+1,r,x,y); return 0; } long long int pwr(int x){ if (x<=0) return 1; else return pw[x]; } long long int DP(){ long long int dp[27][2]; dp[26][0] = dp[26][1] = 1; for (int i=25;i>=0;i--){ if (!qr[i]){ dp[i][0] = dp[i+1][0]; dp[i][1] = dp[i+1][1]; continue; } dp[i][1] = (dp[i+1][1]*pwr(qr[i]-1))%M; dp[i][0] = ((dp[i+1][0]*pwr(qr[i]-1))%M + ((dp[i+1][1] * qr[i])%M * pwr(qr[i]-2))%M)%M; } long long int res = (dp[0][0]-1); if (res<0) res+=M; return res; } int init(){ int i = 1; pw[0] = 1; while(i<=n){ pw[i] = (pw[i-1]*2)%M; i++; } return 0; } int main(){ scanf("%d%d",&n,&m); cin>>s; init(); construct(0,0,n-1); while(m--){ int ch,x,y,t; scanf("%d%d%d",&ch,&x,&y); if (ch==1){ scanf("%d",&t); update(0,0,n-1,x,y,t%26); } else{ query(0,0,n-1,x,y); printf("%lld\n",DP()); memset(qr,0,sizeof(qr)); } } return 0; }