#include using namespace std; #define mp make_pair #define pb push_back typedef long long ll; typedef complex point; typedef pair pii; typedef vector vi; #define DEBUG 0 #define dout if(DEBUG) cout const int MAXN = 1e5 + 5; const ll MOD = 1e9 + 7; const int ALP = 26; ll add(ll a, ll b){ return (a + b + MOD) % MOD; } ll mul(ll a, ll b){ return (a * b + MOD) % MOD; } struct node{ int cnt[ALP]; node(){ for(int i = 0; i < ALP; i++) cnt[i] = 0; } }; node tt[4 * MAXN]; int tt_add[4 * MAXN]; int tmp[ALP]; void update(int v, int num){ for(int i = 0; i < ALP; i++) tmp[i] = tt[v].cnt[i]; for(int i = 0; i < ALP; i++){ int j = (i - num + ALP) % ALP; tt[v].cnt[i] = tmp[j]; } } void update_sum(int v, int v1, int v2){ for(int i = 0; i < ALP; i++){ tt[v].cnt[i] = tt[v1].cnt[i] + tt[v2].cnt[i]; } } void build(int n){ for(int i = n - 2; i >= 0; i--){ update_sum(i, 2 * i + 1, 2 * i + 2); } } void push(int v){ if(tt_add[v]){ int v1 = 2 * v + 1, v2 = 2 * v + 2; tt_add[v1] = (tt_add[v1] + tt_add[v]) % ALP; tt_add[v2] = (tt_add[v2] + tt_add[v]) % ALP; update(v1, tt_add[v]); update(v2, tt_add[v]); tt_add[v] = 0; } } void shif(int v, int tl, int tr, int l, int r, int num){ if(l > r) return; if(tl == l && tr == r){ tt_add[v] = (tt_add[v] + num) % ALP; update(v, num); return; } push(v); int tm = (tl + tr) >> 1; shif(2 * v + 1, tl, tm, l, min(r, tm), num); shif(2 * v + 2, tm + 1, tr, max(l, tm + 1), r, num); update_sum(v, 2 * v + 1, 2 * v + 2); } node zero; node sum(node a, node b){ node c; for(int i = 0; i < ALP; i++){ c.cnt[i] = a.cnt[i] + b.cnt[i]; } return c; } node get_cnt(int v, int tl, int tr, int l, int r){ if(l > r) return zero; if(tl == l && tr == r){ return tt[v]; } push(v); int tm = (tl + tr) >> 1; return sum( get_cnt(2 * v + 1, tl, tm, l, min(r, tm)), get_cnt(2 * v + 2, tm + 1, tr, max(l, tm + 1), r) ); } char s[MAXN]; ll dp[ALP][2]; ll f[MAXN], fr[MAXN]; ll ce[MAXN], co[MAXN]; ll binpow(ll a, ll st){ ll ans = 1; for(; st; st >>= 1){ if(st & 1) ans = mul(ans, a); a = mul(a, a); } return ans; } ll _c(int n, int m){ if(n < m) return 0; return mul(f[n], mul(fr[m], fr[n - m])); } void precalc(){ f[0] = fr[0] = 1; for(int i = 1; i < MAXN; i++){ f[i] = mul(f[i - 1], i); fr[i] = binpow(f[i], MOD - 2); } } ll get_dp(node c){ dout << "DP\n"; for(int i = 0; i < ALP; i++) dout << c.cnt[i]; dout << endl; dp[0][0] = add(binpow(2, c.cnt[0] - 1), -1) ; dp[0][1] = binpow(2, c.cnt[0] - 1); for(int i = 1; i < ALP; i++){ if(!c.cnt[i]){ for(int j = 0; j < 2; j++){ dp[i][j] = dp[i - 1][j]; } continue; } ll cur = binpow(2, c.cnt[i] - 1); dp[i][0] = add(cur, -1); dp[i][1] = cur; dp[i][0] = add(dp[i][0], mul(dp[i - 1][0], cur)); dp[i][1] = add(dp[i][1], mul(dp[i - 1][0], cur)); dp[i][1] = add(dp[i][1], mul(dp[i - 1][1], cur)); } return add(dp[25][0], dp[25][1]); } void solve(){ int n, q; cin >> n >> q; scanf("%s", s); int cnt = 1; while(cnt < n) cnt <<= 1; for(int i = 0; i < n; i++){ int cur = s[i] - 'a'; tt[cnt - 1 + i].cnt[cur] = 1; } build(cnt); int tp, qi, qj, qt; for(int i = 0; i < q; i++){ scanf("%d%d%d", &tp, &qi, &qj); if(tp == 1){ scanf("%d", &qt); shif(0, cnt - 1, 2 * cnt - 2, cnt - 1 + qi, cnt - 1 + qj, qt); } else{ node cur = get_cnt(0, cnt - 1, 2 * cnt - 2, cnt - 1 + qi, cnt - 1 + qj); ll ans = get_dp(cur); printf("%lld\n", ans); } } } int main() { #ifdef NASTYA assert(freopen("input.txt", "r", stdin)); assert(freopen("output.txt", "w", stdout)); #else //assert(freopen(file".in", "r", stdin)); assert(freopen(file".out", "w", stdout)); #endif int t = 1; while(t--) { solve(); } return 0; }