LOJ#6031. 「雅礼集训 2017 Day1」字符串
题解 注意 p*k=定值 那么我们对k进行分情况讨论
当k很小的时候 这时候询问次数会很多 我们考虑直接莫队处理出这次询问所对应子串区间 然后直接对应sam上的right集合即可
当k很大的时候 这时候询问次数会很少 我们暴力枚举每个区间是否属于这次询问 然后logn倍增查询即可
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=2e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m,q,k;
char str[MAXN];
int cur,rt,cnt,fa[MAXN],dis[MAXN],ch[MAXN][26],sz[MAXN];
void built(int x){
int last=cur;cur=++cnt;dis[cur]=dis[last]+1;int p=last;sz[cur]=1;
for(;p&&!ch[p][x];p=fa[p])ch[p][x]=cur;
if(!p)fa[cur]=rt;
else{
int q=ch[p][x];
if(dis[q]==dis[p]+1)fa[cur]=q;
else{
int nt=++cnt;dis[nt]=dis[p]+1;
memcpy(ch[nt],ch[q],sizeof(ch[q]));
fa[nt]=fa[q];fa[q]=fa[cur]=nt;
for(;ch[p][x]==q;p=fa[p])ch[p][x]=nt;
}
}
}
int f[MAXN][21],dep[MAXN];
void dfs(int x,int pre,int deep){
f[x][0]=pre;dep[x]=deep+1;
inc(i,1,20)f[x][i]=f[f[x][i-1]][i-1];
link(x){
dfs(j->t,x,deep+1);
sz[x]+=sz[j->t];
}
}
int calc(int x,int t){
int y=x;
for(int i=20;i>=0;i--){
if(dis[f[y][i]]>=t)y=f[y][i];
}
return sz[y];
}
typedef struct node{
string s;int l,r,id;
}node;
node d[MAXN];
typedef struct Node{
int l,r,id;
}Node;
Node que[MAXN];
int P[MAXN],Sz;
bool cmp(node aa,node bb){
if(P[aa.l]==P[bb.l])return aa.r<bb.r;
else return P[aa.l]<P[bb.l];
}
bool cmp1(Node aaa,Node bbb){
return aaa.r<bbb.r;
}
int num[405][405],Rt[MAXN],Len[MAXN];
ll ans[MAXN];
int main(){
ios::sync_with_stdio(false);
cin>>n>>m>>q>>k;
Sz=sqrt(m);
inc(i,1,m)P[i]=(i-1)/Sz+1;
int base=sqrt(q*k);
cin>>str;
cur=rt=cnt=1;
inc(i,0,n-1)built(str[i]-'a');
inc(i,1,cnt)add(fa[i],i);
dfs(rt,0,0);
inc(i,1,m)cin>>que[i].l>>que[i].r,que[i].l++,que[i].r++,que[i].id=i;
inc(i,1,q)cin>>d[i].s>>d[i].l>>d[i].r,d[i].l++,d[i].r++,d[i].id=i;
if(k<=base){
sort(d+1,d+q+1,cmp);
int L=1;int R=0;
inc(i,1,q){
while(R<d[i].r){
R++;num[que[R].l][que[R].r]++;
}
while(R>d[i].r){
num[que[R].l][que[R].r]--;R--;
}
while(L>d[i].l){
L--;
num[que[L].l][que[L].r]++;
}
while(L<d[i].l){
num[que[L].l][que[L].r]--;L++;
}
int temp=rt;int len1=0;
for(int j=0;j<k;j++){
int t1=d[i].s[j]-'a';
if(ch[temp][t1])temp=ch[temp][t1],len1++;
else{
int pp=temp;
for(;pp&&!ch[pp][t1];pp=fa[pp]);
if(!pp)temp=rt,len1=0;else temp=ch[pp][t1],len1=dis[pp]+1;
}
/*for(int w=j;w>=j-len1+1;w--){
if(!num[w+1][j+1])continue;
ans[d[i].id]+=1ll*num[w+1][j+1]*calc(temp,j-w+1);
}*/
int len2=len1;int ppp=temp;
while(ppp!=rt){
for(int w=j-dis[fa[ppp]];w>=j-len2+1;w--)ans[d[i].id]+=1ll*num[w+1][j+1]*sz[ppp];
ppp=fa[ppp];len2=dis[ppp];
}
}
}
inc(i,1,q)printf("%lld\n",ans[i]);
return 0;
}
else{
sort(que+1,que+m+1,cmp1);
int tot=0;
inc(i,1,q)Rt[i]=rt,Len[i]=0;
inc(i,1,m){
while(tot<k&&tot<que[i].r){
inc(j,1,q){
int t1=d[j].s[tot]-'a';int temp=Rt[j];
if(ch[temp][t1])Rt[j]=ch[temp][t1],Len[j]++;
else{
int pp=temp;
for(;pp&&!ch[pp][t1];pp=fa[pp]);
if(!pp)Rt[j]=rt,Len[j]=0;else Rt[j]=ch[pp][t1],Len[j]=dis[pp]+1;
}
}
tot++;
}
inc(j,1,q){
if(que[i].id>=d[j].l&&que[i].id<=d[j].r){
if(Len[j]<que[i].r-que[i].l+1)continue;
ans[j]+=calc(Rt[j],que[i].r-que[i].l+1);
}
}
}
inc(i,1,q)printf("%lld\n",ans[i]);
}
return 0;
}
#6031. 「雅礼集训 2017 Day1」字符串
内存限制:256 MiB时间限制:1000 ms标准输入输出
题目类型:传统评测方式:文本比较
题目描述
令 s 与 w为两字符串,定义:
- w[l, r]表示字符串 w 在区间 [l, r]中的子串;
- w 在 ss中出现的频率定义为w 在 s 中出现的次数;
- f(s, w, l, r) 表示 w[l, r] 在 s 中出现的频率。
现在给定串 s,m 个区间 [l, r]和长度k,你要回答 q 个询问,每个询问给你一个长度为 k 的字符串 w 和两个整数 a, b求:
输入格式
第一行四个整数 n, m, q, kn,m,q,k,nn 表示 ss 的长度。
接下来一行一个长为 ss 的字符串 ss。
接下来 mm 行,每行两个整数表示 l_i, r_ili,ri。
接下来 qq 行,每行一个字符串 ww,两个整数 a, ba,b。
输出格式
对于每个询问一行,输出答案。
样例
样例输入
8 5 3 3
abacdaba
0 2
1 2
0 0
2 2
1 2
dab 1 4
bac 2 3
eeb 1 3
样例输出
7
3
2

浙公网安备 33010602011771号