#include <iostream>
#include <algorithm>
#include <set>
#include <cstring>
#include <vector>
#include <map>
#include <climits>
using namespace std;

#define SEGMENT_TREE_IMPOSSIBLE -1 
#define SEGMENT_TREE_LENGTH 100005

string arr;
typedef struct node {
    pair<int, int> coord;
    int val;
    struct node * ptr[2];
} node;
int SEGMENT_TREE_ARR[SEGMENT_TREE_LENGTH];
node* mknode(int x, int y) {
    node* nod = new node;
    nod->coord.first = x;
    nod->coord.second = y;
    //Set to some impossible value
    nod->val = SEGMENT_TREE_IMPOSSIBLE;
    for (int i = 0; i < 2; ++i)
        nod->ptr[i] = NULL;
    return nod;
}
node*  build(int xl, int xh){
    if (xl > xh)
        return NULL;
    node* nod = mknode(xl, xh);

    if (xh == xl){
        return nod;
    }

    nod->ptr[0] = build(xl, xl + (xh-xl)/2);
    nod->ptr[1] = build(xl+(xh-xl)/2+1, xh);
    return nod;
}
/*
 * it gives the cumulative values for the values a and b for two segment trees
 */
int club(node*,node*);
node* Max(node* nod){
    if (nod == NULL)
        return nod;
    if (nod->val != SEGMENT_TREE_IMPOSSIBLE)
        return nod;
    //only one element is in the segment tree. The value is taken from the initially stored array SEGMENT_TREE_ARR
    if (nod->coord.first == nod->coord.second){
        nod->val = SEGMENT_TREE_ARR[nod->coord.second];
        return nod;
    }
    //return the value obtained after clubbing from all of its children
    Max(nod->ptr[0]);
    Max(nod->ptr[1]);
    nod->val = club(nod->ptr[0], nod->ptr[1]);
    //cout << nod->coord.first <<' '<< nod->coord.second  << ' ' << nod->val << endl;
    return nod;
}
int mquery(int x,int y, node* nod){
    //query outside the current segment tree's range or the segment tree is null
    if (nod == NULL || y < nod->coord.first || nod->coord.second < x)
        return 0;

    //all elements in the segment tree are surely in the query. That is, segment tree is a subset or equal to the query
    if (x <= nod->coord.first && nod->coord.second <= y){
        return nod->val;
    }
    //call the query recursively on the children of the segment tree.
    int ans = mquery(x, y, nod->ptr[0]) + mquery(x, y, nod->ptr[1]);
    //x,y region definitely has some part of left and right child both
    if (nod->ptr[0] && nod->ptr[1] && x <= nod->ptr[0]->coord.second && nod->ptr[1]->coord.first <= y)
    if (arr[nod->ptr[0]->coord.second] == 'A' && arr[nod->ptr[1]->coord.first] == 'C')
        ans++;
    return ans;
}
int main()
{
    int q;
    int n;
    cin >> n >> q;
    cin >> arr;
    node* mx = build(0, n-1);
    for (int i = 0; i < n; ++i)
        SEGMENT_TREE_ARR[i] = 0;
    Max(mx);
   // cout << endl << endl << endl << endl;
    for (int i = 0; i < q; ++i){
        int x, y;
        scanf("%d%d", &x, &y);
        printf("%d\n", mquery(x-1, y-1, mx));
    }
    return 0;
}
int club(node* a,node* b){
    if (a == NULL && b == NULL){
        return 0;
    }
    if (a == NULL)
        return b->val;
    if (b == NULL)
        return a->val;
    int ans = a->val + b->val;
    if (arr[a->coord.second] == 'A' && arr[b->coord.first] == 'C')
        ans++;
    //printf("\n[club] a[%d,%d], b[%d, %d], res = %d\n", a->coord.first, a->coord.second, b->coord.first, b->coord.second, ans);
    return ans;
}


Measured memory_bytes: 10752