loj

注意到每次询问串长度都是给定的,并且询问串长\(k*\)询问次数\(q<10^5\),所以这里面一个东西大的时候另一个东西就小,那么考虑对较小的下功夫

如果\(k\le \sqrt{n}\),那么可以\(O(k^2)\)暴力枚举询问串的每一个子串,然后在\(S\)的sam找到这个子串对应的点,算出出现次数,并且乘上在区间\([a,b]\)中这个子串询问的出现次数.找到子串对应的点为了方便,可以依次让询问串的某个前缀在sam上匹配,然后按长度从大到小枚举前缀的后缀,从匹配位置开始倍增跳父亲,直到当前点包含的串的长度区间包含当前长度;然后子串在区间\([a,b]\)询问次数可以主席树(雾).所以这部分复杂度是\(O(qk^2logn)=O(n\sqrt{n}logn)\)

如果\(k> \sqrt{n}\),那么\(q\le \sqrt{n}\),所以可以枚举\(m\)个询问区间对应的子串,分别算答案.具体实现可以参考上面,依次用前缀在sam上匹配,然后处理右端点为当前位置的询问子串贡献.这部分是\(O(qmlogn)=O(n\sqrt{n}logn)\)

然后不知道为什么我的倍增被卡了...应该是我写丑了吧qwq.然后改成暴力跳父亲就跑的飞快

#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double using namespace std;
const int N=1e5+10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int n,m,q,kk,lz;
char cc[N],ss[N];
struct SAM
{
int fa[N<<1][19],len[N<<1],ch[N<<1][26],sz[N<<1],la,tt;
vector<int> e[N<<1];
SAM(){la=tt=1;}
void extd(int cx)
{
int np=++tt,p=la;
len[np]=len[p]+1,sz[np]=1,la=tt;
while(!ch[p][cx]) ch[p][cx]=np,p=fa[p][0];
if(!p) fa[np][0]=1;
else
{
int q=ch[p][cx];
if(len[q]==len[p]+1) fa[np][0]=q;
else
{
int nq=++tt;
fa[nq][0]=fa[q][0],len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(int)*26);
fa[np][0]=fa[q][0]=nq;
while(ch[p][cx]==q) ch[p][cx]=nq,p=fa[p][0];
}
}
}
void dfs(int x)
{
for(int j=1;j<=lz;++j)
{
fa[x][j]=fa[fa[x][j-1]][j-1];
if(!fa[x][j]) break;
}
vector<int>::iterator it;
for(it=e[x].begin();it!=e[x].end();++it)
{
int y=*it;
dfs(y),sz[x]+=sz[y];
}
}
void inii()
{
for(int i=2;i<=tt;++i) e[fa[i][0]].push_back(i);
dfs(1);
}
}sam;
namespace ct1
{
int id[320][320],tti;
int s[N*20],ch[N*20][2],rt[N],tt;
void inst(int o1,int o2,int x)
{
int l=1,r=tti;
s[o1]=s[o2]+1;
while(l<r)
{
int mid=(l+r)>>1;
if(x<=mid)
{
ch[o1][0]=++tt,ch[o1][1]=ch[o2][1];
o1=ch[o1][0],o2=ch[o2][0];
r=mid;
}
else
{
ch[o1][0]=ch[o2][0],ch[o1][1]=++tt;
o1=ch[o1][1],o2=ch[o2][1];
l=mid+1;
}
s[o1]=s[o2]+1;
}
}
int quer(int o1,int o2,int l,int r,int lx)
{
if(!s[o1]) return 0;
if(l==r) return s[o1]-s[o2];
int mid=(l+r)>>1;
if(lx<=mid) return quer(ch[o1][0],ch[o2][0],l,mid,lx);
else return quer(ch[o1][1],ch[o2][1],mid+1,r,lx);
}
void wk()
{
for(int i=1;i<=kk;++i)
for(int j=i;j<=kk;++j)
id[i][j]=++tti;
for(int i=1;i<=m;++i)
{
int l=rd()+1,r=rd()+1;
inst(rt[i]=++tt,rt[i-1],id[l][r]);
}
while(q--)
{
scanf("%s",ss+1);
int a=rd()+1,b=rd()+1;
LL ans=0;
for(int i=1,p=1,ll=0;i<=kk;++i)
{
while(p>1&&!sam.ch[p][ss[i]-'a']) p=sam.fa[p][0],ll=sam.len[p];
if(sam.ch[p][ss[i]-'a'])
{
p=sam.ch[p][ss[i]-'a'],++ll;
int x=p,nm;
for(int j=i-ll+1;j<=i;++j)
if((nm=quer(rt[b],rt[a-1],1,tti,id[j][i])))
{
if(sam.len[sam.fa[x][0]]+1>i-j+1)
{
for(int k=lz;~k;--k)
if(sam.len[sam.fa[sam.fa[x][k]][0]]+1>i-j+1)
x=sam.fa[x][k];
x=sam.fa[x][0];
}
ans+=1ll*sam.sz[x]*nm;
}
}
else p=1,ll=0;
}
printf("%lld\n",ans);
}
}
}
namespace ct2
{
struct node
{
int l,i;
bool operator < (const node &bb) const {return l<bb.l;}
};
vector<node> qr[N];
void wk()
{
for(int i=1;i<=m;++i)
{
int l=rd()+1,r=rd()+1;
qr[r].push_back((node){l,i});
}
for(int i=1;i<=n;++i) sort(qr[i].begin(),qr[i].end());
while(q--)
{
scanf("%s",ss+1);
int a=rd()+1,b=rd()+1;
LL ans=0;
for(int i=1,p=1,ll=0;i<=kk;++i)
{
while(p>1&&!sam.ch[p][ss[i]-'a']) p=sam.fa[p][0],ll=sam.len[p];
if(sam.ch[p][ss[i]-'a'])
{
p=sam.ch[p][ss[i]-'a'],++ll;
int x=p;
vector<node>::iterator it;
for(it=qr[i].begin();it!=qr[i].end();++it)
{
int j=(*it).l,ii=(*it).i;
if(i-j+1<=ll&&ii>=a&&ii<=b)
{
/*if(sam.len[sam.fa[x][0]]+1>i-j+1)
{
for(int k=lz;~k;--k)
if(sam.len[sam.fa[sam.fa[x][k]][0]]+1>i-j+1)
x=sam.fa[x][k];
x=sam.fa[x][0];
}*/
while(sam.len[sam.fa[x][0]]+1>i-j+1) x=sam.fa[x][0];
ans+=sam.sz[x];
}
}
}
else p=1,ll=0;
}
printf("%lld\n",ans);
}
}
} int main()
{
n=rd(),m=rd(),q=rd(),kk=rd();
scanf("%s",cc+1);
for(int i=1;i<=n;++i) sam.extd(cc[i]-'a');
lz=log2(n),sam.inii();
if(kk<=315) ct1::wk();
else ct2::wk();
return 0;
}

loj 6031「雅礼集训 2017 Day1」字符串的更多相关文章

  1. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

  2. loj#6031. 「雅礼集训 2017 Day1」字符串(SAM 广义SAM 数据分治)

    题意 链接 Sol \(10^5\)次询问每次询问\(10^5\)个区间..这种题第一感觉就是根号/数据分治的模型. \(K\)是个定值这个很关键. 考虑\(K\)比较小的情况,可以直接暴力建SAM, ...

  3. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

  4. [LOJ 6029]「雅礼集训 2017 Day1」市场

    [LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...

  5. loj#6030. 「雅礼集训 2017 Day1」矩阵(贪心 构造)

    题意 链接 Sol 自己都不知道自己怎么做出来的系列 不难观察出几个性质: 最优策略一定是先把某一行弄黑,然后再用这一行去覆盖不是全黑的列 无解当且仅当无黑色.否则第一个黑色所在的行\(i\)可以先把 ...

  6. loj#6029. 「雅礼集训 2017 Day1」市场(线段树)

    题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...

  7. LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法

    题目描述 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商 ...

  8. 「雅礼集训 2017 Day1」字符串 SAM、根号分治

    LOJ 注意到\(qk \leq 10^5\),我们很不自然地考虑根号分治: 当\(k > \sqrt{10^5}\),此时\(q\)比较小,与\(qm\)相关的算法比较适合.对串\(s\)建S ...

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

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

随机推荐

  1. layui template list

    //第一步:编写模版.你可以使用一个script标签存放模板,如: <script id="demo" type="text/html"> < ...

  2. vscode 插件推荐 - 献给所有前端工程师(2018.4.29更新)

    大家好,我是Moer.VScode现在已经越来越完善.性能远超Atom和webstorm,你有什么理由不用它?在这里,我会给你们推荐很多实用的插件,让你对 vscode 有更深刻的体会,渐渐地你就会知 ...

  3. VLC-Qt 入门指南

      关于 VLC-Qt VLC-Qt:一个结合了 Qt 应用程序和 libVLC 的免费开源库.它包含了用于媒体播放的核心类,以及用于更快速地进行媒体播放器开发的一些 GUI 类. 官网地址:http ...

  4. 卸载apache

    1.查看httpd相关软件包 rpm -qa|grep httpd 2.卸载命令, “rpm -e 软件或服务名” 如果出现类似“httpd >= 2.2.0 is needed by (ins ...

  5. __declspec(dllexport)的使用

    1. 用法 在 VS 的“预编译”选项里定义_EXPORTING宏 #ifdef _EXPORTING #define API_DECLSPEC __declspec(dllexport) #else ...

  6. 用js脚本实现链接

    使用json实现分页的时候,扩展了一下如何使用JS现实链接,其实很简单,但是之前我没用过... 就以分页的上一页,下一页来举例: <script type="text/javascri ...

  7. 对opencv读取的图片进行像素调整(1080, 1920) 1.cv2.VideoCapture(构造图片读取) 2.cv2.nameWindow(构建视频显示的窗口) 3.cv2.setWindowProperty(设置图片窗口的像素) 4.video_capture(对图片像素进行设置)

    1. cv2.VideoCapture(0) #构建视频抓捕器 参数说明:0表示需要启动的摄像头,这里也可以写视频的路径 2. cv2.nameWindow(name, cv2.WINDOW_NORM ...

  8. 生成ip地址表的不同姿势--脚本生成和echo命令生成

    前段时间参加了几个线下的靶机攻防比赛,几十个队伍,如果攻击的时候一个个攻击就非常麻烦,浪费时间.所以需要批量攻击.批量攻击就需要一个完整的ip地址表.在这里总结一下... 有不足的地方欢迎评论 一.脚 ...

  9. linux系统交互通道

    默认有6个命令交互通道和一个图形界面交互通道,默认进入到的是图形界面通道     命令交互模式切换:ctrl+alt+f1---f6     图形交互界面 ctrl+alt+f7 1.图形界面交互模式 ...

  10. Appium移动自动化测试(五)之应用操作

    实验简介 对于APP测试来讲, 除了进行功能测试以外, 安装和卸载其实也是一个很重要的测试项. 试想, 如果用脚本来实现了, 可以事先判断该应用是否已安装, 根据判断结果来执行安装和卸载的动作, 循环 ...