#include <iostream>
#include <string>
#include <sstream>
#include <string_view>
#include <map>
int main()
{
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
std::string line;
std::getline(std::cin, line);
std::stringstream linestream(std::move(line));
int n, q;
if (!(linestream >> n >> q) {
throw std::runtime_error("Fail 1");
}
std::string s;
std::getline(std::cin, s);
// Personally, I need convincing this is a valid optimization
// creating the tree is relatively trivial but still far
// more costly than summing a set of integers. You would
// have to have some long strings and lots of repeats before
// this becomes worth it.
// Also this technical could be improved by allowing for
// totally enclosed substrings to be used in calculating the
// length for larger strings.
std::map<std::string_view, int> memo;
for(int loop = 0; loop < q; loop++){
line.clear();
std::getline(std::cin, line);
std::stringstream linestream(std::move(line));
int l,r, length;
if (!(linestream >> l >> r)) {
throw std::runtime_error("Fail 2");
}
std::string_view key(&s[l], (r - l + 1));
auto find = memo.find(key);
if (find == memo.end()) {
length = 0;
for(auto val: key) {
// Not sure about this.
// Need some unit tests.
length += std::islower(val) ? val - 'a' + 1: 0;
}
memo[key] = length;
}
else {
length = find->second;
}
std::cout << length << "\n";
}
}