The meaning of problems
Noting the length of the query string \ (K \) is given, while \ (\ SUM \ Limits len_w KQ = \ leqslant10. 5 ^ \) , we found \ (k, q \) between one another must be large will be small, so we \ (k \) Category talk:
first, be sure to pair \ (s \) to build a suffix automaton, the maintenance on each point \ (endpos \) size of the collection.
\(k\geqslant\sqrt{n}\)
At this time \ (Q \ leqslant \ n-sqrt {} \) , we directly \ (the SAM \) matching violent \ (W \) , identify all \ (W \) prefix corresponding to a node, then enumeration interrogation, multiplying jump \ (w [l_i ... r_i] \) of this node, the coupled node answers \ (endpos \) set size to.
\(k<\sqrt{n}\)
At this time \ (m \) species group interrogation little, we can enumerate \ (W \) of all sub-strings, it is calculated \ ([l, r] \ ) the number of occurrences of this interrogation interval, multiplied by its answer added to the answer.
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define pii pair<int,int>
#define mkp make_pair
#define fir first
#define sec second
const int maxn=2e5+10;
const int maxt=410;
int n,m,Q,K,tot,cnt_edge,t;
int head[maxn],size[maxn],pos[maxn],posl[maxn];
int f[maxn][18];
char s[maxn];
inline int read()
{
char c=getchar();re int res=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
return res*f;
}
struct edge{int to,nxt;}e[maxn];
inline void add_edge(int u,int v)
{
e[++cnt_edge].nxt=head[u];
head[u]=cnt_edge;
e[cnt_edge].to=v;
}
struct Query{int l,r;}qr[maxn];
struct SAM
{
int last,tot;
int fa[maxn],len[maxn];
int ch[maxn][26];
SAM(){last=tot=1;}
inline void add(int c)
{
re int now=++tot;len[now]=len[last]+1;
re int p=last;last=now;
while(p&&!ch[p][c])ch[p][c]=now,p=fa[p];
if(!p){fa[now]=1;return;}
re int q=ch[p][c];
if(len[q]==len[p]+1)fa[now]=q;
else
{
re int nowq=++tot;len[nowq]=len[p]+1;
memcpy(ch[nowq],ch[q],sizeof(ch[q]));
fa[nowq]=fa[q];fa[q]=fa[now]=nowq;
while(p&&ch[p][c]==q)ch[p][c]=nowq,p=fa[p];
}
}
}sam;
void dfs(int x)
{
for(re int i=1;i<=17;i++)f[x][i]=f[f[x][i-1]][i-1];
for(re int i=head[x];i;i=e[i].nxt)
{
re int y=e[i].to;
f[y][0]=x;dfs(y);
size[x]+=size[y];
}
}
inline void solve1()
{
vector<int>a[maxt][maxt];
for(int i=1;i<=m;i++)a[qr[i].l][qr[i].r].push_back(i);
while(Q--)
{
scanf("%s",s+1);
int l=read()+1,r=read()+1;
ll res=0;
for(int i=1;i<=K;i++)
for(int j=i,now=1;j<=K;j++)
{
now=sam.ch[now][s[j]-'a'];
if(!now)break;
int ql=lower_bound(a[i][j].begin(),a[i][j].end(),l)-a[i][j].begin();
int qr=upper_bound(a[i][j].begin(),a[i][j].end(),r)-a[i][j].begin();
res+=1ll*(qr-ql)*size[now];
}
printf("%lld\n",res);
}
}
inline int find(int l,int r)
{
re int now=pos[r];
for(re int i=17;~i;i--)if(sam.len[f[now][i]]>=min(r-l+1,posl[r]))now=f[now][i];
return now;
}
inline int solve(int l,int r)
{
if(!pos[r]||posl[r]<(r-l+1))return 0;;
re int now=find(l,r);
if(sam.len[now]>=r-l+1)return size[now];
else return 0;
}
inline void solve2()
{
while(Q--)
{
scanf("%s",s+1);
re int l=read()+1,r=read()+1;
re int now=1,nowl=0,res=0;
for(re int i=1;i<=K;i++)
{
re int c=s[i]-'a';
while(!sam.ch[now][c]&&now)now=sam.fa[now],nowl=sam.len[now];
if(!now){now=1;pos[i]=1;nowl=0;posl[i]=0;continue;}
now=sam.ch[now][c];pos[i]=now;
nowl++;posl[i]=nowl;
}
for(re int i=l;i<=r;i++)res+=solve(qr[i].l,qr[i].r);
printf("%d\n",res);
}
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
n=read(),m=read(),Q=read(),K=read();t=330;
scanf("%s",s+1);
for(re int i=1;i<=n;i++)sam.add(s[i]-'a'),size[sam.last]=1;
for(re int i=2;i<=sam.tot;i++)add_edge(sam.fa[i],i);
dfs(1);
for(re int i=1;i<=m;i++)qr[i].l=read()+1,qr[i].r=read()+1;
if(K<=t)solve1();
else solve2();
return 0;
}