LOJ #6031 字符串
Description
Solution
当 \(k\) 值较小时,发现询问串比较多,串长比较小
然后对 \(Q\) 个询问区间离线跑莫队,一次考虑每一个区间的贡献
假设一个区间 \([i,j]\) 出现的次数是 \(c[i][j]\),然后 \(O(k^2)\) 求出每一个区间的贡献,乘上 \(c[i][j]\) 就是答案
当 \(k\) 值较大时,询问次数比较少,串长比较大
考虑与询问次数有关的做法
对于每一个询问,预处理出 \(w\) 的每一个前缀在 \(S\) 的 \(SAM\) 中匹配到的位置和匹配的长度
右端点固定时,左端点移动形成的串就是这个右端点对应的前缀的后缀,每一次跳父亲就可以跳到
倍增到合法长度的节点即可
显然 \(k\) 取 \(\sqrt{10^5}\) 时最优
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>void gi(T &x){
int f;char c;
for (f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for (x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=2e5+10,M=320,B=20;
int n,m,Q,K,ch[N][26],fa[N],cur=1,cnt=1,len[N],sz[N],sa[N],c[N],g[N];
char s[N];
inline void ins(int c){
int p=cur;cur=++cnt;len[cur]=len[p]+1;
for(;p && !ch[p][c];p=fa[p])ch[p][c]=cur;
if(!p)fa[cur]=1;
else{
int q=ch[p][c];
if(len[p]+1==len[q])fa[cur]=q;
else{
int nt=++cnt;len[nt]=len[p]+1;
memcpy(ch[nt],ch[q],sizeof(ch[q]));
fa[nt]=fa[q];fa[q]=fa[cur]=nt;
for(;p && ch[p][c]==q;p=fa[p])ch[p][c]=nt;
}
}sz[cur]=1;
}
inline void priwork(){
for(int i=1;i<=cnt;i++)c[len[i]]++;
for(int i=1;i<=n;i++)c[i]+=c[i-1];
for(int i=cnt;i>=1;i--)sa[c[len[i]]--]=i;
for(int i=cnt;i>=1;i--)sz[fa[sa[i]]]+=sz[sa[i]];
}
struct D{int l,r;}e[N];
struct data{int l,r,id;}q[N];
inline bool comp(data i,data j){return i.l/B!=j.l/B?i.l/B<j.l/B:i.r<j.r;}
namespace solo{
char w[N][M];int v[M][M];ll ans[N];
inline void add(int x){v[e[x].l][e[x].r]++;}
inline void del(int x){v[e[x].l][e[x].r]--;}
inline ll solve(int x){
int len=strlen(w[x]+1),p,c;ll ret=0;
for(int i=1;i<=len;i++){
p=1;
for(int j=i;j<=len;j++){
c=w[x][j]-'a';
if(!ch[p][c])break;
p=ch[p][c];
ret+=v[i][j]*sz[p];
}
}
return ret;
}
void main(){
for(int i=1;i<=Q;i++){
scanf("%s",w[i]+1);
gi(q[i].l);gi(q[i].r);q[i].id=i;q[i].l++;q[i].r++;
}
sort(q+1,q+Q+1,comp);
int l=1,r=0;
for(int i=1;i<=Q;i++){
while(r<q[i].r)add(++r);
while(l>q[i].l)add(--l);
while(r>q[i].r)del(r--);
while(l<q[i].l)del(l++);
ans[q[i].id]=solve(q[i].id);
}
for(int i=1;i<=Q;i++)printf("%lld\n",ans[i]);
}
}
namespace sol{
char w[N];int pos[N],f[N][20];
inline int qry(int x,int y){
if(len[x]<y)return 0;
for(int i=19;i>=0;i--)
if(f[x][i] && len[f[x][i]]>=y)x=f[x][i];
return sz[x];
}
void main(){
int x,y,le,p,now;
for(int i=1;i<=cnt;i++)f[i][0]=fa[i];
for(int j=1;j<20;j++)
for(int i=1;i<=cnt;i++)f[i][j]=f[f[i][j-1]][j-1];
for(int i=1;i<=Q;i++){
scanf("%s",w+1);le=strlen(w+1);
p=1;now=0;
for(int j=1;j<=le;j++){
int c=w[j]-'a';
if(ch[p][c])p=ch[p][c],now++;
else{
while(p>1 && !ch[p][c])p=fa[p];
if(ch[p][c])now=len[p]+1,p=ch[p][c];
else now=0;
}
pos[j]=p;g[j]=now;
}
gi(x);gi(y);x++;y++;
ll ret=0;
for(int j=x;j<=y;j++)
if(g[e[j].r]>=e[j].r-e[j].l+1)
ret+=qry(pos[e[j].r],e[j].r-e[j].l+1);
printf("%lld\n",ret);
}
}
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>m>>Q>>K;
scanf("%s",s+1);
for(int i=1;i<=n;i++)ins(s[i]-'a');
priwork();
for(int i=1;i<=m;i++)gi(e[i].l),gi(e[i].r),e[i].l++,e[i].r++;
if(K<M)solo::main();
else sol::main();
return 0;
}
LOJ #6031 字符串的更多相关文章
- [LOJ 6031]「雅礼集训 2017 Day1」字符串
[LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...
- loj 6031「雅礼集训 2017 Day1」字符串
loj 注意到每次询问串长度都是给定的,并且询问串长\(k*\)询问次数\(q<10^5\),所以这里面一个东西大的时候另一个东西就小,那么考虑对较小的下功夫 如果\(k\le \sqrt{n} ...
- loj#6031. 「雅礼集训 2017 Day1」字符串(SAM 广义SAM 数据分治)
题意 链接 Sol \(10^5\)次询问每次询问\(10^5\)个区间..这种题第一感觉就是根号/数据分治的模型. \(K\)是个定值这个很关键. 考虑\(K\)比较小的情况,可以直接暴力建SAM, ...
- 【SAM】loj#6401. 字符串
网上有篇题解写的是线段树合并维护求值? 题目描述 有一个只包含小写字母,长度为 $n$ 的字符串 $S$ .有一些字母是好的,剩下的是坏的. 定义一个子串 $S_{l\ldots r}$是好的,当且仅 ...
- 雅礼集训 2017 Day1
T1:loj 6029 市场 题目大意: 维护一个数据结构支持区间加 区间除法 区间求最小值 区间求和 思路: 用线段树维护区间加 区间求最小值 区间和 对于区间除法 注意到除数d很大而加法的w很小 ...
- Contest Record
Contest 1135 at HZOI Problem A: 优美的棋发现一个可以证明的规律就是了……忘记给<<运算的左边变量转化为long long类型了,结果挂了20分……以后一定记 ...
- 【LOJ#3095】[SNOI2019]字符串(后缀数组)
[LOJ#3095][SNOI2019]字符串(后缀数组) 题面 LOJ 题解 首先画图看看如何比较两个串的大小,发现这个东西等价于求两个相邻的后缀的\(LCP\). 一个做法是求出\(SA\),然后 ...
- LOJ 3049: 洛谷 P5284: 「十二省联考 2019」字符串问题
题目传送门:LOJ #3049. 题意简述: 给定一个长度为 \(n\) 的母串 \(S\). 有 \(n_a\) 个 A 类串,都是 \(S\) 的子串,以区间的形式给出. 有 \(n_b\) 个 ...
- LOJ #6436. 「PKUSC2018」神仙的游戏(字符串+NTT)
题面 LOJ #6436. 「PKUSC2018」神仙的游戏 题解 参考 yyb 的口中的长郡最强选手 租酥雨大佬的博客 ... 一开始以为 通配符匹配 就是类似于 BZOJ 4259: 残缺的字符串 ...
随机推荐
- 【Alpha版本】冲刺阶段 - Day5 - 破浪
今日进展 袁逸灏:解决音乐播放问题以及跳转问题.(5h) 刘伟康:大致检查了测试规范,参考了其他 alpha 阶段的博客.(1h) 刘先润:解决了敌车与障碍物溢出边界的代码问题,给用户车辆增加了火焰喷 ...
- C语言--第三周作业
一.PTA作业中4个题目 1.7-9 A乘以B 要求:输入的两个整数:A是你学号前两位数字,B是你学号后两位数字 a.代码 #include <stdio.h> int main () { ...
- configparser 练习
[kaixin]xxx = 333name = hahheh = 0[erick]age = 123555xxx = ooo555name = hah555 1 import configparser ...
- ES6常用新特性
https://segmentfault.com/a/1190000011976770?share_user=1030000010776722 该文章为转载文章!仅个人喜好收藏文章! 1.前言 前几天 ...
- Spring+Hibernate+Struts(SSH)框架整合
SSH框架整合 前言:有人说,现在还是流行主流框架,SSM都出来很久了,更不要说SSH.我不以为然.现在许多公司所用的老项目还是ssh,如果改成流行框架,需要成本.比如金融IT这一块,数据库dao层还 ...
- python的命名空间
Python的命名空间是Python程序猿必须了解的内容,对Python命名空间的学习,将使我们在本质上掌握一些Python中的琐碎的规则. 接下来我将分四部分揭示Python命名空间的本质:一.命名 ...
- JMeter入门(01)概念和样例
一.概念 JMeter 是一款专门用于功能测试和压力测试的轻量级测试开发平台,实现了许多和互联网相关的网络测试组件,同时还保留着很强的扩展性. JMeter可以用来测试诸如:静态文件,Java Ser ...
- kubernetes入门(07)kubernetes的核心概念(4)
一.pod 二.Volume volume可以为容器提供持久化存储,比如 三.私有镜像 在使用私有镜像时,需要创建一个docker registry secret,并在容器中引用.创建docker r ...
- 【52ABP实战教程】0.3-- 从github推送代码回vsts实现双向同步
需求 在之前的文章中"[DevOps]如何用VSTS持续集成到Github仓库" 我们有讲述如何将vsts中的代码编译推送到github中,这一篇我们来完善,如果有人给你开源项目推 ...
- python、java实现二叉树,细说二叉树添加节点、深度优先(先序、中序、后续)遍历 、广度优先 遍历算法
数据结构可以说是编程的内功心法,掌握好数据结构真的非常重要.目前基本上流行的数据结构都是c和c++版本的,我最近在学习python,尝试着用python实现了二叉树的基本操作.写下一篇博文,总结一下, ...