#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long ll; const int MAXN = 100100; const int MAXSEG = 1<<18; const int MOD = 1000000007; int N, Q; string S; int seg[MAXSEG][26]; int lazy[MAXSEG]; int curq[26]; int temp[26]; ll power[MAXN]; void build_tree(int node, int left, int right) { if (left == right) { seg[node][S[left - 1] - 'a']++; return; } int mid = (left + right)/2; build_tree(2*node, left, mid); build_tree(2*node + 1, mid + 1, right); for (int i = 0; i < 26; i++) seg[node][i] = seg[2*node][i] + seg[2*node + 1][i]; } void shift(int node, int t) { memcpy(temp, seg[node], sizeof(seg[node])); for (int i = 0; i < 26; i++) seg[node][(i + t) % 26] = temp[i]; } void down(int node) { if (lazy[node] > 0) { shift(2*node, lazy[node]); shift(2*node + 1, lazy[node]); lazy[2*node] = (lazy[2*node] + lazy[node]) % 26; lazy[2*node + 1] = (lazy[2*node + 1] + lazy[node]) % 26; lazy[node] = 0; } } void update(int node, int left, int right, int ql, int qr, int t) { if (left > right || ql > qr || right < ql || qr < left) return; if (ql <= left && right <= qr) { shift(node, t); lazy[node] = (lazy[node] + t) % 26; return; } down(node); int mid = (left + right)/2; update(2*node, left, mid, ql, qr, t); update(2*node + 1, mid + 1, right, ql, qr, t); for (int i = 0; i < 26; i++) seg[node][i] = seg[2*node][i] + seg[2*node + 1][i]; } void query(int node, int left, int right, int ql, int qr) { if (left > right || ql > qr || right < ql || qr < left) return; if (ql <= left && right <= qr) { for (int i = 0; i < 26; i++) curq[i] += seg[node][i]; return; } down(node); int mid = (left + right)/2; query(2*node, left, mid, ql, qr); query(2*node + 1, mid + 1, right, ql, qr); } ll go() { ll x = 1, cnt = 0; for (int i = 0; i < 26; i++) if (curq[i] > 0) { x = (x*power[curq[i] - 1]) % MOD; cnt++; } ll ret = (cnt + 1)*x % MOD; ret = (ret - 1) % MOD; if (ret < 0) ret += MOD; return ret; } int main() { ios::sync_with_stdio(0); power[0] = 1; for (int i = 1; i < MAXN; i++) power[i] = power[i - 1] * 2 % MOD; cin >> N >> Q >> S; build_tree(1, 1, N); for (int i = 0, type, ql, qr, t; i < Q; i++) { cin >> type; if (type == 1) { cin >> ql >> qr >> t; ql++, qr++; update(1, 1, N, ql, qr, t % 26); } else { cin >> ql >> qr; ql++, qr++; memset(curq, 0, sizeof(curq)); query(1, 1, N, ql, qr); cout << go() << "\n"; } } return 0; }