题意
求给定字符串的[l,r]区间内不同的子串个数。
注意到n只有2000,对每个后缀建后缀自动机,边往后缀自动机里插入字符,边记录子串个数,对于询问O(1)输出。
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#define N 2010
using namespace std;
int n,t,m,Ans[N][N];
char A[N];
inline char C(){
static char buf[100000],*p1=buf,*p2=buf;
if(p1==p2){
p2=(p1=buf)+fread(buf,1,100000,stdin);
if(p1==p2)return EOF;
}
return *p1++;
}
inline void reaD(int &x){
char Ch=C();x=0;
for(;Ch>'9'||Ch<'0';Ch=C());
for(;Ch>='0'&&Ch<='9';x=x*10+Ch-'0',Ch=C());
}
inline void reaD(char *x){
char Ch=C();int len=0;
for(;Ch>'z'||Ch<'a';Ch=C());
for(;Ch>='a'&&Ch<='z';x[len++]=Ch,Ch=C());x[len]=0;
}
struct SAM_{
int next[N<<3][30],fail[N<<3],stp[N<<3],p,cnt,tot;
SAM_(){p=cnt=1;}
int add(int x){
int np=++cnt;stp[np]=stp[p]+1;
memset(next[np],0,sizeof(next[np]));
while(p&&!next[p][x]) next[p][x]=np,p=fail[p];
if(!p) fail[np]=1;
else{
int q=next[p][x];
if(stp[q]==stp[p]+1) fail[np]=q;
else{
int nq=++cnt;stp[nq]=stp[p]+1;
memset(next[nq],0,sizeof(next[nq]));
memcpy(next[nq],next[q],sizeof(next[q]));
fail[nq]=fail[q];
fail[np]=fail[q]=nq;
while(next[p][x]==q) next[p][x]=nq,p=fail[p];
}
}
p=np;
return tot+=stp[np]-stp[fail[np]];
}
void clear(){
cnt=p=1;tot=0;
memset(next[p],0,sizeof(next[p]));
//memset(next,0,sizeof(next));
//memset(fail,0,sizeof(fail));
//memset(stp,0,sizeof(stp));
}
}SAM;
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
for(reaD(t);t;t--){
reaD(A+1);n=strlen(A+1);
for(int i=1;i<=n;i++){
SAM.clear();
for(int j=i;j<=n;j++)
Ans[i][j]=SAM.add(A[j]-'a');
}
reaD(m);
for(int i=1,a,b;i<=m;i++){
reaD(a);reaD(b);
printf("%d\n",Ans[a][b]);
}
}
return 0;
}