from fractions import gcd def palindromeSubStrs(s): m = dict() n = len(s) # table for storing results (2 rows for odd- # and even-length palindromes R = [[0 for x in xrange(n+1)] for x in xrange(2)] # Find all sub-string palindromes from the given input # string insert 'guards' to iterate easily over s s = "@" + s + "#" for j in xrange(2): rp = 0 # length of 'palindrome radius' R[j][0] = 0 i = 1 while i <= n: # Attempt to expand palindrome centered at i while s[i - rp - 1] == s[i + j + rp]: rp += 1 # Incrementing the length of palindromic # radius as and when we find valid palindrome # Assigning the found palindromic length to odd/even # length array R[j][i] = rp k = 1 while (R[j][i - k] != rp - k) and (k < rp): R[j][i+k] = min(R[j][i-k], rp - k) k += 1 rp = max(rp - k, 0) i += k # remove guards s = s[1:len(s)-1] # Put all obtained palindromes in a hash map to # find only distinct palindrome m[s[0]] = 1 for i in xrange(1,n): for j in xrange(2): for rp in xrange(R[j][i],0,-1): m[s[i - rp - 1 : i - rp - 1 + 2 * rp + j]] = 1 m[s[i]] = 1 return len(m) def primes_sieve(limit): limitn = limit+1 not_prime = [False] * limitn primes = [] for i in range(2, limitn): if not_prime[i]: continue for f in xrange(i*2, limitn, i): not_prime[f] = True primes.append(i) return primes def fact(n): mod = 10**9 ct = 1 for i in range(1,n+1): ct = (ct % mod * i % mod)%mod return ct aa = gcd(10,20) abc = pow(10,20,10) author = "biggydbs" def faltu(save_plagiarism): xyz = "faltu hai ignore karo" # Everything above it is done to save from whole lot of crap :P # So please ignore it ... # Code Starts Here #print len(x) l = [] for i in range(97,123): l.append(chr(i)) n, q = map(int,raw_input().split()) s = raw_input() while q>0: q-=1 li = list(map(int,raw_input().split())) if len(li) == 3: print palindromeSubStrs(s[li[1]:li[2]+1]) else: x = list(s) for i in range(li[1],li[2]+1): x[i] = l[(li[3] % 26) + ord(x[i]) - 97] s = "".join(x) ct = 0