//昨天晚上一直用后缀数组来写,怎么写都超时(后来在网上看到也有用后缀数组过的,然来是自己昨晚sb,用把l,r区间的rank数组排序来使l,r区间内的rank有序,其实直接按rank,O(n)遍历就可以做到),
//今天看了多校3的官方解题,可以用后缀自动机;
//今天上午就去学习了后缀自动机(以前没有主动去学后缀自动机,总想后缀自动机能解的,后缀数组都能解,这次顺便学习一下);
//官方解题说这题后缀自动机可以O(n^2)+O(1),可是我写的后缀自动机时间复杂度还是O(n*q),因为每次计算字串的个数的还是把所有的step遍历了的一遍,
//但是没有重新建树,建树的常数小了一些;
//思考:(不知道计算字串的个数的时候可不可以利用以前的信息,也就是F数组的修改更新可不可以记录下来,去想想,继续学习后缀自动机);
//ac 代码如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<bitset>
#include<string>
#include<queue>
#include<deque>
#include<ctype.h>
#include<vector>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<functional>
#include<algorithm>
using namespace std;
#define N 2010
int F[N*2],ant,last,ch[N*2][26],step[N*2];
void init(){
last=ant=1;
memset(F,0,sizeof(F));
memset(ch,0,sizeof(ch));
memset(step,0,sizeof(step));
}
void ins(int x){
int t=++ant,pa=last;
step[t]=step[last]+1;last=t;
for(;pa&&!ch[pa][x];pa=F[pa]) ch[pa][x]=t;
if(pa==0) F[t]=1;
else if(step[pa]+1==step[ch[pa][x]]) F[t]=ch[pa][x];
else {
int nq=++ant,q=ch[pa][x];
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
step[nq]=step[pa]+1;F[nq]=F[q];F[q]=F[t]=nq;
for(;pa&&ch[pa][x]==q;pa=F[pa]) ch[pa][x]=nq;
}
}
//以上为后缀自动机的部分
char s[N];
int ans[10100];
vector<pair<int,int> > Q[N];
void run(int p){
int i,t,j,tt;
init();
sort(Q[p].begin(),Q[p].end());
for(i=0,t=p-1;i<(int)Q[p].size();i++){
if(i&&Q[p][i].first==t){
ans[Q[p][i].second]=tt; continue;
}
while(t<Q[p][i].first){
ins(s[t]-'a');t++;
}
for(tt=0,j=ant;j>0;j--) tt+=step[j]-step[F[j]];
ans[Q[p][i].second]=tt;
}
}
int main(){
int cas,n,i,a,b,m;
scanf("%d",&cas);
while(cas--){
scanf("%s",s);m=strlen(s);
for(i=1;i<=m;i++) Q[i].clear();
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d",&a,&b);
Q[a].push_back(make_pair(b,i));
}
for(i=1;i<=m;i++) if(Q[i].size()) run(i);
for(i=1;i<=n;i++) printf("%d\n",ans[i]);
}
return 0;
}
//后缀数组修改后ac的代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxn = 2100;
char s[maxn];
int sa[maxn],t[maxn],t2[maxn],c[maxn];
void build_sa(int n,int m){
int i,k,*x=t,*y=t2,p;
//基数排序
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[i]=s[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(k=1;k<n;k*=2){
p=0;
//直接利用sa数组排序第二关键字
for(i=n-k;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
//基数排序第一关键字
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
//根据sa和y数组计算新的x数组
swap(x,y);
p=1; x[sa[0]]=0;
for(i=1;i<n;i++)
x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])?p-1:p++;
if(p>=n)break;
m=p;
}
}
int rank[maxn],height[maxn];
void getHeight(int n)
{
int i,j,k=0;
for(i=1;i<=n;i++) rank[sa[i]] = i;
for(i=0;i<n;i++){
if(rank[i]==1)continue;
if(k)k--;
j=sa[rank[i]-1];
while(s[i+k]==s[j+k])k++;
height[rank[i]]=k;
}
}
int dp[maxn][maxn];
void brute_rmp(int n){
int i,k,ans;
for(k=1;k<=n;k++){
ans=n+n;
for(i=k+1;i<=n;i++){
ans=min(ans,height[i]);
dp[k][i]=ans;
}
}
}
struct node{
int k,d;
}A[maxn];
int M;
int run(int l,int r)
{
int n=r-l+1,i,ans=0,k;
for(i=k=1;i<=M;i++){ //昨天就是sb在这儿(对A[i].k排序),不知道写这个循环来得到一个rank有序的A[]
if(l<=sa[i]&&sa[i]<=r){
A[k].k=i;A[k].d=r-sa[i]+1;k++;
}if(k>n) break;
}
ans+=A[1].d;
int b=1;
for(i=2;i<=n;i++){
ans+=A[i].d-min(A[i].d,min(A[b].d,dp[A[b].k][A[i].k]));
if(A[b].d>A[i].d&&dp[A[b].k][A[i].k]>=A[i].d); else b=i;
}
return ans;
}
int main(){
int cas,n,a,b;
scanf("%d",&cas);
while(cas--){
scanf("%s",s);
M=strlen(s);
build_sa(M+1,255);
getHeight(M);brute_rmp(M);
scanf("%d",&n);
while(n--){
scanf("%d%d",&a,&b);
printf("%d\n",run(a-1,b-1));
}
}
return 0;
}