P5112 FZOUTSY
建个后缀自动机,当然这里得反着建
找到最小的大于k的子串,相当于最小满足的子串,\(endpos\)最大,然后沿\(parents\)边都染成同一色
同色的都满足后缀的最长公共前缀满足大于k,接下来就是莫队在树上跑
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn=10000000;
inline LL Read(){
LL x=0,f=1; char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<3)+(x<<1)+c-'0'; c=getchar();
}return x*f;
}
LL n,m,K,last,nod,num,tot,size,pieces;
LL col[maxn],ans[maxn],len[maxn],fail[maxn],son[maxn][7],head[maxn];
LL belong[maxn],cnt[maxn];
LL ch[500];
char s[maxn];
inline void Init(){
last=n+1,nod=n+1;
for(LL i=1;i<=n;++i)
len[i]=i;
}
inline void Insert(LL c,LL now){
LL p=last;
last=now;
while(p&&!son[p][c])
son[p][c]=now,
p=fail[p];
if(!p)
fail[now]=n+1;
else{
LL q=son[p][c];
if(len[q]==len[p]+1)
fail[now]=q;
else{
LL nq=++nod;
len[nq]=len[p]+1;
memcpy(son[nq],son[q],sizeof(son[q]));
fail[nq]=fail[q], fail[q]=fail[now]=nq;
while(p&&son[p][c]==q)
son[p][c]=nq,
p=fail[p];
}
}
}
struct code{
LL to,next;
}dis[maxn];
inline void Add(LL u,LL v){
dis[++num]=(code){v,head[u]},head[u]=num;
}
inline void Build(){
for(LL i=1;i<=nod;++i)
Add(fail[i],i);
}
void Dfs(LL u,LL co){
if(u<=n)
col[u]=co;
if(co)
for(LL i=head[u];i;i=dis[i].next)
Dfs(dis[i].to,co);
else
for(LL i=head[u];i;i=dis[i].next){
LL v=dis[i].to;
if(len[v]>=K)
Dfs(v,++tot);
else
Dfs(v,0);
}
}
struct node{
LL l,r,id;
}q[maxn];
inline bool cmp(node x,node y){
return (belong[x.l]^belong[y.l])?
belong[x.l]<belong[y.l]:
(belong[x.l]&1)?
x.r<y.r:x.r>y.r;
}
LL sum;
inline void Inc(LL x){
x=col[x];
if(x)
sum+=cnt[x],cnt[x]++;
}
inline void Del(LL x){
x=col[x];
if(x)
cnt[x]--,
sum-=cnt[x];
}
int main(){
ch['y']=0,ch['u']=1,ch['z']=2,ch['s']=3,ch['o']=4,ch['f']=5,ch['t']=6;
n=Read(),m=Read(),K=Read();
scanf(" %s",s+1);
Init();
for(LL i=n,j=1;i>=1;--i,++j)
Insert(ch[s[i]],j);
Build();
Dfs(n+1,(K==0));
for(LL i=1;i<=(n/2);++i)
swap(col[i],col[n-i+1]);
for(LL i=1;i<=m;++i){
LL l=Read(),r=Read();
q[i]=(node){l,r,i};
}
size=ceil((double)n/sqrt(m));
pieces=n/size;
for(LL i=1;i<=pieces;++i)
for(LL j=(i-1)*pieces+1;j<=i*pieces;++j)
belong[j]=i;
sort(q+1,q+1+m,cmp);
LL l=1,r=0;
for(LL i=1;i<=m;++i){
LL ql=q[i].l,qr=q[i].r,x;
while(l<ql)
Del(l++);
while(l>ql)
Inc(--l);
while(r<qr)
Inc(++r);
while(r>qr)
Del(r--);
ans[q[i].id]=sum;
}
for(LL i=1;i<=m;++i)
printf("%lld\n",ans[i]);
return 0;
}