import java.io.*; import java.util.*; import java.math.BigInteger; import java.util.Map.Entry; import static java.lang.Math.*; public class Solution extends PrintWriter { final int k = 'z' - 'a' + 1; class Node { final int f, t; final int[] cnt = new int[k]; final Node l, r; int s; Node(int index, int c) { f = t = index; l = r = null; cnt[c] = 1; } Node(Node l, Node r) { this.f = l.f; this.t = r.t; this.l = l; this.r = r; for (int c = 0; c < k; c++) { this.cnt[c] = l.cnt[c] + r.cnt[c]; } } void shift(int from, int to, int val) { if (to < from || t < from || to < f) { return; } if (from <= f && t <= to) { s = (s + val) % k; } else { if (s != 0 && l != r) { l.shift(f, t, s); r.shift(f, t, s); } s = 0; l.shift(from, to, val); r.shift(from, to, val); Arrays.fill(cnt, 0); l.cnt(f, t, cnt); r.cnt(f, t, cnt); } } void cnt(int from, int to, int[] cnt) { if (to < from || t < from || to < f) { return; } if (from <= f && t <= to) { for (int c = 0; c < k; c++) { cnt[c] += this.cnt[(c + k - s) % k]; } return; } else { if (s != 0 && l != r) { l.shift(f, t, s); r.shift(f, t, s); } s = 0; l.cnt(from, to, cnt); r.cnt(from, to, cnt); } } } final long mod = 1_000_000_000 + 7; long pow(long a, long b) { long c = 1; for (; b > 0; b /= 2) { if (b % 2 == 1) { c = (c * a) % mod; } a = (a * a) % mod; } return c; } void run() { int n = nextInt(), q = nextInt(); long[] row = new long[n + 3]; long[] inv = new long[n + 3]; row[0] = row[1] = 1; for (int i = 2; i < row.length; i++) { row[i] = (row[i - 1] * 2) % mod; } for (int i = 0; i < inv.length; i++) { inv[i] = pow(row[i], mod - 2); } String str = next(); Node[] node = new Node[n]; for (int i = 0; i < n; i++) { node[i] = new Node(i, str.charAt(i) - 'a'); } while (n > 1) { int t = 0; for (int i = 1; i < n; i += 2) { node[t++] = new Node(node[i - 1], node[i]); } if (n % 2 == 1) { node[t++] = node[n - 1]; } n = t; } Node root = node[0]; int[] cnt = new int[k]; for (int i = 0; i < q; i++) { int t = nextInt(), l = nextInt(), r = nextInt(); if (t == 1) { root.shift(l, r, nextInt()); } if (t == 2) { Arrays.fill(cnt, 0); root.cnt(l, r, cnt); // println(Arrays.toString(cnt)); long peven = 1; for (int c = 0; c < k; c++) { peven = (peven * row[cnt[c]]) % mod; } long sum = peven; for (int c = 0; c < k; c++) { long prod = (peven * inv[cnt[c]]) % mod; prod = (prod * (row[cnt[c] + 1] - row[cnt[c]] + mod)) % mod; sum = (sum + prod) % mod; } println((sum - 1 + mod) % mod); } } } int[][] nextMatrix(int n, int m) { int[][] matrix = new int[n][m]; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) matrix[i][j] = nextInt(); return matrix; } String next() { while (!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(nextLine()); return tokenizer.nextToken(); } boolean hasNext() { while (!tokenizer.hasMoreTokens()) { String line = nextLine(); if (line == null) { return false; } tokenizer = new StringTokenizer(line); } return true; } int[] nextArray(int n) { int[] array = new int[n]; for (int i = 0; i < n; i++) { array[i] = nextInt(); } return array; } int nextInt() { return Integer.parseInt(next()); } long nextLong() { return Long.parseLong(next()); } double nextDouble() { return Double.parseDouble(next()); } String nextLine() { try { return reader.readLine(); } catch (IOException err) { return null; } } public Solution(OutputStream outputStream) { super(outputStream); } static BufferedReader reader; static StringTokenizer tokenizer = new StringTokenizer(""); static Random rnd = new Random(); public static void main(String[] args) throws IOException { reader = new BufferedReader(new InputStreamReader(System.in)); Solution solution = new Solution(System.out); solution.run(); solution.close(); reader.close(); } }