\ (SAM \) + Category talk
First to build a \ (SAM \) and then calculated the \ (| {\ rm endpos} (p) | \)
$ \ Sum w = kq \ leq 10 ^ 5 $, then to \ (K \) size classification discussed.
\ (K \ GEQ \ n-sqrt \) , \ (Q \ Leq \ n-sqrt \) , directly in the \ (the SAM \) matching \ (W \) , each position is determined in \ (the SAM \) points on . For each interrogation, multiplication jump upwardly against the upper most and \ ({\ rm len} ( p) \ geq qr-ql + 1 \) point, plus answer \ (| {\ rm endpos} (p) | \) .
In this case Q \ leqslant \ sqrt {} n- Q ⩽ n- , we direct the SAM S A M violence matching W W , find all W W prefix corresponding to a node, then enumeration interrogation, multiplication jump w [l_i .. .r_i] W [ L I ... R & lt I ] of this node, together with the answer of the node endpos E * n- D P O * S ** size can be set.
\ (K <\ n-sqrt \) , \ (Q> \ n-sqrt \) , consider the case \ (qK ^ 2 \) algorithm, we can start a tub \ (v [ql] [qr ] \) Record All inquiries, and enumerate \ (W \) all prefixes match, it was separated in two \ ([a, b] \ ) frequency interval this query appears, by the added length of the matching answers.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=200010,B=17,D=350;
int n,m,Q,K,tot=1,lst=1;
int LL[N],RR[N],f[N][B+1];
int fa[N],c[N][26],len[N],d[N],sz[N],mem[N];
char s[N];
inline void add(int ch) {
R p=lst,np=lst=++tot;
len[np]=len[p]+1,++sz[tot];
while(p&&!c[p][ch]) c[p][ch]=np,p=fa[p];
if(!p) return fa[np]=1,void();
R q=c[p][ch];
if(len[q]==len[p]+1) return fa[np]=q,void();
else {
R nq=++tot;
memcpy(c[nq],c[q],26<<2);
fa[nq]=fa[q],len[nq]=len[p]+1;
fa[np]=fa[q]=nq;
while(p&&c[p][ch]==q) c[p][ch]=nq,p=fa[p];
}
}
int mp[N],ml[N];
inline void solve1() {
register ll ans;
for(R i=1;i<=m;++i) LL[i]=g()+1,RR[i]=g()+1;
while(Q--) {
scanf("%s",s+1);
R ql=g()+1,qr=g()+1;
R p=1,l=0;
for(R i=1;i<=K;++i) {
R ch=s[i]-'a';
while(p&&!c[p][ch]) p=fa[p],l=len[p];
if(!p) {p=1,l=0,mp[i]=0; continue;}
p=c[p][ch],++l,mp[i]=p,ml[i]=l;
} ans=0;
for(R i=ql,p,l,lim;i<=qr;++i) {
p=mp[RR[i]],l=ml[RR[i]],lim=RR[i]-LL[i]+1;
if(!p||l<lim) continue;
for(R t=B;~t;--t) if(f[p][t]&&len[f[p][t]]>=lim)
p=f[p][t];
ans+=sz[p];
} printf("%lld\n",ans);
}
}
vector<int> q[D][D];
inline void solve2() {
register ll ans=0;
for(R i=1,l,r;i<=m;++i)
l=g()+1,r=g()+1,q[l][r].push_back(i);
while(Q--) {
ans=0;
scanf("%s",s+1);
R ql=g()+1,qr=g()+1;
for(R i=1;i<=K;++i) for(R j=i,p=1;j<=K;++j) {
p=c[p][s[j]-'a']; if(!p) break;
ans+=1ll*(upper_bound(q[i][j].begin(),q[i][j].end(),qr)-
lower_bound(q[i][j].begin(),q[i][j].end(),ql))*sz[p];
} printf("%lld\n",ans);
}
}
inline void main() {
n=g(),m=g(),Q=g(),K=g();
scanf("%s",s+1);
for(R i=1;i<=n;++i) add(s[i]-'a');
for(R i=1;i<=tot;++i) ++d[len[i]];
for(R i=1;i<=n;++i) d[i]+=d[i-1];
for(R i=1;i<=tot;++i) mem[d[len[i]]--]=i;
for(R i=tot;i;--i) sz[fa[mem[i]]]+=sz[mem[i]];
for(R i=1;i<=tot;++i) f[i][0]=fa[i];
for(R t=1;t<=B;++t) for(R i=1;i<=tot;++i)
f[i][t]=f[f[i][t-1]][t-1];
if(K>=sqrt(n)) solve1();
else solve2();
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.10