//#define _GLIBCXX_DEBUG #include using namespace std; #define pb push_back #define mp make_pair typedef long long ll; typedef vector vi; typedef vector vvi; typedef vector vll; typedef pair pii; typedef vector vii; #define sz(c) (int)(c).size() #define ALL(c) (c).begin(), (c).end() const int mod = (int)1e9 + 7; const int let = 26; void add (int &a, int b) { a += b; if (a >= mod) a -= mod; } void sub (int &a, int b) { a -= b; if (a < 0) a += mod; } int mult (int a, int b) { return (ll)a * b % mod; } struct segtree { vvi vals; vi shift; int tsz = 1; segtree (const string &s) { while (tsz <= sz(s)) tsz *= 2; shift.assign(2 * tsz, 0); vals.assign(2 * tsz, vi(let, 0)); for (int i = tsz; i < tsz + sz(s); i++) vals[i][s[i - tsz] - 'a']++; for (int i = tsz - 1; i >= 1; i--) vals[i] = sum(vals[2 * i], vals[2 * i + 1]); } void apply (int v, int j) { assert(0 <= j && j < let); shift[v] = (shift[v] + j) % let; if (j != 0) rotate(vals[v].begin(), vals[v].begin() + let - j, vals[v].end()); } void push (int v) { if (shift[v] != 0) { for (int j = 2 * v; j <= 2 * v + 1; j++) apply(j, shift[v]); shift[v] = 0; } } vi sum (const vi &l, const vi &r) { vi ans(let); assert(sz(l) == let && sz(r) == let); for (int i = 0; i < let; i++) ans[i] = l[i] + r[i]; return ans; } vi getseg (int v, int l, int r, int L, int R) { if (L == l && r == R) return vals[v]; push(v); const int M = (L + R) / 2; if (r <= M) return getseg(2 * v, l, r, L, M); if (l >= M) return getseg(2 * v + 1, l, r, M, R); return sum(getseg(2 * v, l, M, L, M), getseg(2 * v + 1, M, r, M, R)); } vi getseg (int l, int r) { return getseg(1, l, r, 0, tsz); } void shiftseg (int v, int l, int r, int L, int R, int t) { if (L == l && r == R) { apply(v, t); return; } push(v); const int M = (L + R) / 2; if (r <= M) shiftseg(2 * v, l, r, L, M, t); else if (l >= M) shiftseg(2 * v + 1, l, r, M, R, t); else { shiftseg(2 * v, l, M, L, M, t); shiftseg(2 * v + 1, M, r, M, R, t); } vals[v] = sum(vals[2 * v], vals[2 * v + 1]); } void shiftseg (int l, int r, int t) { shiftseg(1, l, r, 0, tsz, t); } }; //struct segtree //{ // string s; // // segtree (const string &s_) : s(s_) {} // // int shiftseg (int l, int r, int t) // { // for (int i = l; i < r; i++) // s[i] = (s[i] - 'a' + t) % let + 'a'; // } // // vi getseg (int l, int r) // { // vi ans(let); // for (int i = l; i < r; i++) // ans[s[i] - 'a']++; // return ans; // } //}; void solve (int n) { int q; string s; cin >> q >> s; assert(sz(s) == n); segtree data(s); vi pw(n + 1, 1); for (int i = 1; i <= n; i++) pw[i] = mult(pw[i - 1], 2); for (int i = 0; i < q; i++) { int tp, l, r; cin >> tp >> l >> r; ++r; if (tp == 1) { int t; cin >> t; t %= let; data.shiftseg(l, r, t); } else if (tp == 2) { vi res = data.getseg(l, r); int dp[let + 1][2]; memset(dp, 0, sizeof dp); dp[0][0] = 1; for (int j = 0; j < let; j++) { const int even = (res[j] == 0 ? 1 : pw[res[j] - 1]); const int odd = (res[j] == 0 ? 0 : pw[res[j] - 1]); add(dp[j + 1][0], mult(dp[j][0], even)); add(dp[j + 1][1], mult(dp[j][1], even)); add(dp[j + 1][1], mult(dp[j][0], odd)); } int ans = dp[let][0]; add(ans, dp[let][1]); sub(ans, 1); cout << ans << '\n'; } else assert(false); } } int main() { ios_base::sync_with_stdio(false); cin.tie(0); int n; while (cin >> n) solve(n); }