import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.StringTokenizer; public class Solution implements Runnable { private void solve() throws IOException { int N = nextInt(); int Q = nextInt(); char[] ch = reader.readLine().toCharArray(); long[] add = new long[ch.length + 2]; long MOD = 1_000_000_007; for(int q = 0; q < Q; ++q) { StringTokenizer st = new StringTokenizer(reader.readLine()); if(st.countTokens() == 4) { st.nextToken(); int start = Integer.parseInt(st.nextToken()); int end = Integer.parseInt(st.nextToken()); int times = Integer.parseInt(st.nextToken()); for(int z = start; z <= end; ++z) { add[z] += times; add[z] %= 26; } } else { StringBuilder sb = new StringBuilder(""); st.nextToken(); int start = Integer.parseInt(st.nextToken()); int end = Integer.parseInt(st.nextToken()); for(int z = start; z <= end; ++z) sb.append(shift(ch[z],add[z])); int NN = sb.length(); long[][] dp = new long[NN+1][NN+1]; for(int i = 0; i < NN; ++i) dp[i][i] = 1; for(int l = 2; l <= NN; ++l) { for(int j = 0; j < NN; ++j) { int cut = l + j - 1; if(cut < NN) { if (sb.charAt(j) == sb.charAt(cut)) { dp[j][cut] = dp[j][cut - 1] + dp[j + 1][cut] + 1; dp[j][cut] %= MOD; } else { dp[j][cut] = dp[j][cut - 1] + dp[j + 1][cut] - dp[j + 1][cut - 1]; dp[j][cut] %= MOD; } } } } writer.println((dp[0][NN-1]%MOD)); } } } private char shift(char c, long times) { int m = (c-'a')%26; m += times; m %= 26; return (char)('a' + m); } public static void main(String[] args) { new Solution().run(); } BufferedReader reader; // BufferedReader reader2; StringTokenizer tokenizer; PrintWriter writer; // BufferedWriter writer; public void run() { try { reader = new BufferedReader(new InputStreamReader(System.in)); // reader = new BufferedReader(new FileReader("trees.in")); // reader2 = new BufferedReader(new FileReader("1.in")); tokenizer = null; writer = new PrintWriter(System.out); // writer = new PrintWriter("trees.out"); // writer = new BufferedWriter(System.out); // writer = new BufferedWriter(new OutputStreamWriter(System.out)); solve(); reader.close(); // reader2.close(); writer.close(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } int nextInt() throws IOException { return Integer.parseInt(nextToken()); } long nextLong() throws IOException { return Long.parseLong(nextToken()); } double nextDouble() throws IOException { return Double.parseDouble(nextToken()); } short nextShort() throws IOException { return Short.parseShort(nextToken()); } String nextToken() throws IOException { while (tokenizer == null || !tokenizer.hasMoreTokens()) { tokenizer = new StringTokenizer(reader.readLine()); } return tokenizer.nextToken(); } }