/*
此代码的主要思路是来自yxc大神的;不过这个代码全是我自己写的;
*/
#include <iostream>
#include <string.h>
using namespace std;
typedef unsigned long long ull;
const int base=131,N = 1000010;
/*
long long 是2^63 左右,而 unsigned long long 应该是 2^64 ;当一个数超过了2^64
这样就会对其进行2^64 取余;
base 最好的是131进制 或者13331进制 ,这是经过大量的实验总结出来的;
*/
ull h[N],p[N];
/*
h存的是前i位对应的hash;
比如串 abcdefg
h[1] 对应的是 a 的hash ;
h[2] 对应的是 ab 的 hash;
h[3] 对应的是abc 的 hash;
*/
char s[N];
/*
这是我们的字符串
*/
/*
这是求某子串的hash ;
这样我们就可以在o(1)的时间来访问每个子串的hash;
*/
ull getSum(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1];
}
int main()
{
h[0]=0;p[0]=1;
scanf("%s",s+1);
/*
至于这个输入我也没看懂,反正就是从让其下标从1开始;(自己试出来的)
*/
int len=strlen(s+1);
for(int i=1;i<=len;i++)
{
h[i]=h[i-1]*base+s[i]-'a'+1;
/*
因为前面提到
*/
p[i]=p[i-1]*base;//(分别对应的是131的i次幂)
}
/*
下面是对字串的测试;
比如abcabcabc
如果你输入m=3的话
再输入l r
l = 1,r = 3
l = 4,r = 6
l = 7,r = 9
这三个的hash的值是一样的;
*/
int m;
int l,r;
cin>>m;
while(m--)
{
cin>>l>>r;
cout<<getSum(l,r)<<endl;
}
return 0;
}