#include using namespace std; #define fn "main" #define long long long #define ve vector #define vi ve #define xx first #define yy second #define sz(v) ((int) v.size()) #define inf(type) (numeric_limits::max()) #define ii pair #define sz(v) ((int) v.size()) const long mod = 1e9 + 7; long mpow(long base, long m) { long ans = 1; for(; m > 0; m >>= 1) { if (m & 1) ans = (ans * base) % mod; base = (base * base) % mod; } return ans; } int n, q; string a; ve seg; vi lz; struct node { int ll, rr, id; node(int l, int r, int i): ll(l), rr(r), id(i) {} node left() { return node(ll, (ll + rr) / 2, id * 2); } node right() { return node((ll + rr) / 2 + 1, rr, id * 2 + 1); } void downdate() { for (int i = 0; i < 26; ++i) seg[id][i] = seg[id * 2][i] + seg[id * 2 + 1][i]; } void diffuse() { if (ll > rr or lz[id] == 0) return ; vi t = seg[id]; for (int i = 0; i < 26; ++i) seg[id][(i + lz[id]) % 26] = t[i]; if (ll < rr) lz[id * 2] = (lz[id * 2] + lz[id]) % 26, lz[id * 2 + 1] = (lz[id * 2 + 1] + lz[id]) % 26; lz[id] = 0; } void build() { if (ll == rr) seg[id][a[ll] - 'a'] = 1; if (ll >= rr) return; left().build(); right().build(); downdate(); } void update(int l, int r, int t) { diffuse(); if (ll > rr or l > rr or ll > r) return; if (l <= ll and rr <= r) { lz[id] = (lz[id] + t) % 26; diffuse(); return; } left().update(l, r, t); right().update(l, r, t); downdate(); } void query(int l, int r, vi& ans) { diffuse(); if (ll > rr or l > rr or ll > r) return; if (l <= ll and rr <= r) { for (int i = 0; i < 26; ++i) ans[i] += seg[id][i]; return; } left().query(l, r, ans); right().query(l, r, ans); } }; node root() { return node(0, sz(seg) / 4 - 1, 1); } long countway(const vi& a) { long ans = 0; long cnt = 1; for (int i = 0; i < 26; ++i) { if (a[i] == 0) continue; cnt = (cnt * mpow(2, a[i] - 1)) % mod; } ans = cnt; for (int i = 0; i < 26; ++i) { if (a[i] == 0) continue; long t1 = mpow(2, a[i] - 1); long t2 = ((mpow(2, a[i]) - t1) % mod + mod) % mod; long t = (cnt * mpow(t1, mod - 2)) % mod; t = (t * t2) % mod; ans = (ans + t) % mod; } return ans - 1; } int main() { #ifdef OFFLINE_JUDGE freopen(fn".inp", "r", stdin); freopen(fn".out", "w", stdout); #endif // OFFLINE_JUDGE ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> q >> a; seg.resize(4 * n, vi(26)); lz.resize(4 * n); root().build(); while (q--) { int t, l, r; cin >> t >> l >> r; if (t == 1) { cin >> t; root().update(l, r, t); } else { vi m(26); root().query(l, r, m); cout << countway(m) << '\n'; } } return 0; }