为了方便,用$N=10^{5}$来描述复杂度

(对原串建立SAM)注意到$\sum|w|=qk\le N$,考虑对$q$和$k$的大小关系分类讨论:

1.若$q\le k$,即询问次数较少,将其与原串建立一个广义SAM,然后找到枚举所有区间,倍增找到该区间对应子串的位置,该right集合大小即为答案,时间复杂度为$o(qN\log N)$

(建立广义SAM的实际操作,由于只关心于$s$的子串,并不需要新建节点,会更方便一些)

2.若$k<q$,即串长较短,直接暴力枚举查询串的所有子串,并在原串的SAM上查询其出现次数(即对应节点的right集合大小),然后统计其在$[l_{a},r_{a}],[l_{a+1},r_{a+1}],...,[l_{b},r_{b}]$中出现了几次:

将$m$个区间中相同区间存储位置到同一个vector中,然后即查询该区间对应的vector有几个元素在$[a,b]$中,通过二分即可,时间复杂度为$o(qk^{2}\log N)=o(Nk\log N)$

显然总复杂度为$O(N\sqrt{N}\log N)$,可以通过

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define ll long long
5 vector<int>v[N];
6 int V,n,m,q,l,lst,a,b,nex[N],len[N],R[N],ch[N][26],A[N],B[N],pos[N],Len[N],fa[N][20];
7 ll ans;
8 char s[N],ss[N];
9 void add(int c){
10 int p=lst,np=lst=++V;
11 len[np]=len[p]+1;
12 while ((p)&&(!ch[p][c])){
13 ch[p][c]=np;
14 p=nex[p];
15 }
16 if (!p)nex[np]=1;
17 else{
18 int q=ch[p][c];
19 if (len[q]==len[p]+1)nex[np]=q;
20 else{
21 int nq=++V;
22 nex[nq]=nex[q];
23 nex[q]=nex[np]=nq;
24 len[nq]=len[p]+1;
25 memcpy(ch[nq],ch[q],sizeof(ch[q]));
26 while ((p)&&(ch[p][c]==q)){
27 ch[p][c]=nq;
28 p=nex[p];
29 }
30 }
31 }
32 }
33 void dfs(int k,int f){
34 fa[k][0]=f;
35 for(int i=1;i<20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
36 for(int i=0;i<v[k].size();i++){
37 dfs(v[k][i],k);
38 R[k]+=R[v[k][i]];
39 }
40 }
41 int get(int k,int l){
42 for(int i=19;i>=0;i--)
43 if (len[fa[k][i]]>=l)k=fa[k][i];
44 return k;
45 }
46 int main(){
47 scanf("%d%d%d%d%s",&n,&m,&q,&l,s);
48 for(int i=0;i<m;i++)scanf("%d%d",&A[i],&B[i]);
49 V=lst=1;
50 for(int i=0;i<n;i++){
51 add(s[i]-'a');
52 R[lst]=1;
53 }
54 for(int i=2;i<=V;i++)v[nex[i]].push_back(i);
55 dfs(1,0);
56 if (q<=l){
57 for(int ii=1;ii<=q;ii++){
58 scanf("%s%d%d",ss,&a,&b);
59 ans=0;
60 for(int i=0,k=1;i<l;i++){
61 while ((k>1)&&(!ch[k][ss[i]-'a']))k=nex[k];
62 Len[i]=len[k];
63 if (i)Len[i]=min(Len[i],Len[i-1]);
64 if (ch[k][ss[i]-'a']){
65 k=ch[k][ss[i]-'a'];
66 Len[i]++;
67 }
68 pos[i]=k;
69 }
70 for(int j=a;j<=b;j++)
71 if (Len[B[j]]>=B[j]-A[j]+1)ans+=R[get(pos[B[j]],B[j]-A[j]+1)];
72 printf("%lld\n",ans);
73 }
74 }
75 else{
76 for(int i=0;i<l*l;i++)v[i].clear();
77 for(int i=0;i<m;i++)v[A[i]*l+B[i]].push_back(i);
78 for(int ii=1;ii<=q;ii++){
79 scanf("%s%d%d",ss,&a,&b);
80 ans=0;
81 for(int i=0;i<l;i++)
82 for(int j=i,k=1;j<l;j++){
83 k=ch[k][ss[j]-'a'];
84 if (!k)break;
85 int p=i*l+j;
86 int posl=lower_bound(v[p].begin(),v[p].end(),a)-v[p].begin();
87 int posr=upper_bound(v[p].begin(),v[p].end(),b)-v[p].begin()-1;
88 ans+=(ll)R[k]*max(posr-posl+1,0);
89 }
90 printf("%lld\n",ans);
91 }
92 }
93 return 0;
94 }

[loj6031]字符串的更多相关文章

  1. [LOJ6029~6052]雅礼集训 2017 选做

    Link 代码可以在loj上看我的提交记录. Day 1 [LOJ6029]市场 对于一次除法操作,若区间内所有数的减少量均相同则可视作区间减法,否则暴力递归下去.显然一个线段树节点只会被暴力递归进去 ...

  2. loj6031「雅礼集训 2017 Day1」字符串

    题目 首先先对\(s\)建一个\(\operatorname{SAM}\),设\(w=kq\) 发现\(k,q\leq 10^5\),但是\(w\leq 10^5\),于是套路地根号讨论一下 如果\( ...

  3. 并不对劲的Loj6031:「雅礼集训 2017 Day1」字符串

    题目传送门:-> 看到题目的第一反应当然是暴力:对于串s建后缀自动机,每次询问中,求w对应的子串在s的SAM中的right集合.O(qmk)听上去显然过不了. 数据范围有个∑w<=1e5, ...

  4. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  5. 测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率

    之前一篇里写过字符串常用类的三种方式<java中的字符串相关知识整理>,只不过这个只是分析并不知道他们之间会有多大的区别,或者所谓的StringBuffer能提升多少拼接效率呢?为此写个简 ...

  6. java中的字符串相关知识整理

    字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...

  7. JavaScript 字符串实用常操纪要

    JavaScript 字符串用于存储和处理文本.因此在编写 JS 代码之时她总如影随形,在你处理用户的输入数据的时候,在读取或设置 DOM 对象的属性时,在操作 Cookie 时,在转换各种不同 Da ...

  8. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  9. Redis的简单动态字符串实现

    Redis 没有直接使用 C 语言传统的字符串表示(以空字符结尾的字符数组,以下简称 C 字符串), 而是自己构建了一种名为简单动态字符串(simple dynamic string,sds)的抽象类 ...

随机推荐

  1. 生成base64图片验证码

    github.com/mojocn/base64Captcha func GetCaptcha(c *gin.Context){ driver := base64Captcha.NewDriverDi ...

  2. 洛谷2805 [NOI2009]植物大战僵尸 (拓扑排序+最小割)

    坚决抵制长题面的题目! 首先观察到这个题目中,我们会发现,我们对于原图中的保护关系(一个点右边的点对于这个点也算是保护) 相当于一种依赖. 那么不难看出这个题实际上是一个最大权闭合子图模型. 我们直接 ...

  3. CF49E Common ancestor(dp+dp+dp)

    纪念卡常把自己卡死的一次自闭模拟赛 QWQ 一开始看这个题,以为是个图论,仔细一想,貌似可以直接dp啊. 首先,因为规则只有从两个变为1个,貌似可以用类似区间\(dp\)的方式来\(check\)一段 ...

  4. Java:volatile笔记

    Java:volatile笔记 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 1. volatile 和 JMM 内存模型的可见性 JUC 下的三个包 java ...

  5. Java:并发笔记-02

    Java:并发笔记-02 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 3. 共享模型之管程-1 本章内容-1 共享问题 synchronized 线程安全分 ...

  6. 第31篇-方法调用指令之invokevirtual

    invokevirtual字节码指令的模板定义如下: def(Bytecodes::_invokevirtual , ubcp|disp|clvm|____, vtos, vtos, invokevi ...

  7. Uniapp云打包生成apk下载链接

    使用uni[]()app云打包生成安装包下载链接 manifest.json 中配置自动获取appid manifest.json中配置app 图标 按教程生成.keystore证书 使用云打包生成安 ...

  8. NB-IoT的DRX、eDRX、PSM三个模式怎么用?通俗解释,看完就懂!

    面我们讲了不少NB-IOT的应用.软件和硬件设计的变动. (链接在文章末尾). 今天讲讲NB-IoT的三大模式,在各种物联网和智能硬件场景中的使用方法 DRX.eDRx.PSM是什么? DRX虽然叫做 ...

  9. STM32直流电机启动(一)驱动电路的介绍

    驱动电路 典型的H桥驱动电路如下:要使电机旋转只需导通对角线上的两个三极管即可,如导通Q1,Q4,关闭Q2,Q4即可驱动电机正转:若想电机反向转动,即导通三极管Q2,Q3,关闭Q1,Q4.此时电路图可 ...

  10. stm32学习笔记之GPIO功能框图分析

    GPIO 是通用输入输出端口的简称,简单来说就是STM32 可控制的引脚,STM32 芯片的GPIO 引脚与外部设备连接起来,从而实现与外部通讯.控制以及数据采集的功能.STM32 芯片的GPIO被分 ...