文字列S $ $ $ Q $の時間を考えると、[L、R] $サブストリング異なった部分文字列が$ Sの本質ではありませんどのように多くのたびにクエリ文字列$ T $を尋ねました。
問題解決の時間
質問に少しハのように。
しかし、この時間は、あなたは$ S $に$ T $をマッチさせたいです。
関係なく、選択したセグメント$ S $のレッツ・異なるたびに、我々は(それが68pts前に、あること)を選択SAM $ S $セグメントを構築していることを前提としてい
私たちは、直接$ T $の試合を設置、メンテナンスが試合に$ lnow今最長の長さ$で、$ときPX $スキップ$ tranc $ $ lnow ++ $、
不一致PXは$ $ $にスキップすると$をlenの対応する点$を変更$ lnow $、$を事前。
しかし、再ビルドSAMのそれを再び$ S $には明らかではないたびに。
したがって、上記の整合動作が$か$ endposの$の範囲内である時点で$ [L、R]で照会することができる考えます。
以下のようなセグメントツリーのマージを書きます。
このとき、上記のマッチング操作は手順は、それを変更するために必要とされる「不一致」。
通常は、ここで$ $ $前ではなくlnow $にジャンプの後に直接変更されます。
なぜなら:$知ら$ lnow文字列$ T $、$ $ををch、我々はポイント$ X $にマッチしたと仮定し、
私たちは$ tranc [X] [CH] $ [L + lnow、R] $間隔の$であるクエリにしたいです。
だから、$ lnow-- $不一致に$ lnow == lenになるまで$前$をジャンプするとき$ [X] [前]。
明らかに、この試合はまだ$ O(nlogn)$、ツリーラインからのログです。
そして、逃げます。
$ T $ $ lnow = MA上に設け$ I $の文字をマッチング[i]は$、
$ ANS = \シグマ(SAM T上の各ノード)でlen [X] -max(LEN [プレ[X]、MA [IP [X]])$
($ Ipが[X] $ $ X $は、TSAMの一つは$ T $の文字に対応した時点を意味します)
醜いパッケージ-1000
#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
namespace RKK
{
const int N=2000011;
int TAT;
char s0[N],s1[N];int l0,l1;
int rt[N],tcnt,lson[N*44],rson[N*44];
struct sumireko{int to,ne;}e[N];int he[N],ecnt;
void addline(int f,int t){e[++ecnt].to=t;e[ecnt].ne=he[f],he[f]=ecnt;}
void insert(int x,int &px,int pl,int pr)
{
if(!px) px=++tcnt;
if(pl==pr) return;
int pm=pl+pr>>1;
if(x<=pm) insert(x,lson[px],pl,pm);
else insert(x,rson[px],pm+1,pr);
}
int merge(int px,int py,int pl,int pr)
{
if(!px||!py) return px|py;
int pz=++tcnt;
if(pl!=pr)
{
int pm=pl+pr>>1;
lson[pz]=merge(lson[px],lson[py],pl,pm);
rson[pz]=merge(rson[px],rson[py],pm+1,pr);
}
return pz;
}
int query(int l,int r,int px,int pl,int pr)
{
if(l>r||!px) return 0;
if(l<=pl&&r>=pr) return 1;
int pm=pl+pr>>1;
int ret=0;
if(l<=pm) ret|=query(l,r,lson[px],pl,pm);
if(r>pm) ret|=query(l,r,rson[px],pm+1,pr);
return ret;
}
struct remilia{int tranc[26],len,pre;};
int ma[N];
struct sakuya
{
remilia s[N];
int ip[N];
int fin,size;
sakuya(){fin=size=1;}
void set(){memset(s,0,sizeof(remilia)*(size+10)),memset(ip,0,sizeof(int)*(size+10)),fin=size=1;}
void ins(int ch,int i=0)
{
int npx,npy,lpx,lpy;
npx=++size;
s[npx].len=s[fin].len+1;ip[npx]=i;
for(lpx=fin;lpx&&!s[lpx].tranc[ch];lpx=s[lpx].pre) s[lpx].tranc[ch]=npx;
if(!lpx) s[npx].pre=1;
else
{
lpy=s[lpx].tranc[ch];
if(s[lpy].len==s[lpx].len+1) s[npx].pre=lpy;
else
{
npy=++size;
s[npy]=s[lpy],ip[npy]=ip[lpy];
s[npy].len=s[lpx].len+1;
s[npx].pre=s[lpy].pre=npy;
while(s[lpx].tranc[ch]==lpy)
{
s[lpx].tranc[ch]=npy;
lpx=s[lpx].pre;
}
}
}
fin=npx;
}
void dfs(int x)
{
for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to) dfs(t),rt[x]=merge(rt[x],rt[t],1,l0);
}
void work()
{
for(int i=2;i<=size;i++) addline(s[i].pre,i);
dfs(1);
}
}sam,sam1;
void work(int l,int r)
{
sam1.set();
for(int i=1;i<=l1;i++) sam1.ins(s1[i]-'a',i);
int px=1,lnow=0;
for(int i=1;i<=l1;i++)
{
while(px!=1&&!query(l+lnow,r,rt[sam.s[px].tranc[s1[i]-'a']],1,l0))
{
lnow--;
if(lnow==sam.s[sam.s[px].pre].len) px=sam.s[px].pre;
}
if(query(l+lnow,r,rt[sam.s[px].tranc[s1[i]-'a']],1,l0))
{
lnow++;
px=sam.s[px].tranc[s1[i]-'a'];
}
ma[i]=lnow;
}
lint ans=0;
for(int i=2;i<=sam1.size;i++) ans+=max(0,sam1.s[i].len-max(sam1.s[sam1.s[i].pre].len,ma[sam1.ip[i]]));
printf("%lld\n",ans);
memset(ma,0,sizeof(int)*(l1+5));
}
int Iris()
{
scanf("%s",s0+1),l0=strlen(s0+1);
for(int i=1;i<=l0;i++) sam.ins(s0[i]-'a'),insert(i,rt[sam.fin],1,l0);
sam.work();
scanf("%d",&TAT);
for(int rkk=1,l,r;rkk<=TAT;rkk++)
{
scanf("%s%d%d",s1+1,&l,&r),l1=strlen(s1+1);
work(l,r);
}
return 0;
}
}
int main(){return RKK::Iris();}