//昨天晚上一直用后缀数组来写,怎么写都超时(后来在网上看到也有用后缀数组过的,然来是自己昨晚sb,用把l,r区间的rank数组排序来使l,r区间内的rank有序,其实直接按rank,O(n)遍历就可以做到),
//今天看了多校3的官方解题,可以用后缀自动机;
//今天上午就去学习了后缀自动机(以前没有主动去学后缀自动机,总想后缀自动机能解的,后缀数组都能解,这次顺便学习一下);
//官方解题说这题后缀自动机可以O(n^2)+O(1),可是我写的后缀自动机时间复杂度还是O(n*q),因为每次计算字串的个数的还是把所有的step遍历了的一遍,
//但是没有重新建树,建树的常数小了一些;
//思考:(不知道计算字串的个数的时候可不可以利用以前的信息,也就是F数组的修改更新可不可以记录下来,去想想,继续学习后缀自动机);
//ac 代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//后缀数组修改后ac的代码
#include
#include
#include
#include
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=0;i--) sa[--c[x[i]]]=i;
for(k=1;k=k) y[p++]=sa[i]-k;
//基数排序第一关键字
for(i=0;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)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;in) 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;
}