题意:给定主串s和m个模式串,每次询问[l,r]的模式串中出现s[pl...pr]次数最多的串和次数。

这题挺简单的,先把所有模式串拿来建广义后缀自动机,询问相当于子树众数,用线段树合并即可。

那我为什么写这题题解呢?

1.作为我博客第一道非BZOJ题。

2.作为我博客第一道写题意(英文)的题。

3.这题是老师留的作业,所以可以骗访问量。

4.记录一下广义后缀自动机的优秀写法,以前我是无脑建的。

#include <cstdio>
#include <algorithm>
using namespace std;
#define l(x) t[x].l
#define r(x) t[x].r
#define M ((L+R)>>1) typedef pair<int,int> pr;
const int S=,N=;
char s[N],sr[S];
int m,e,q,l1,r1,l2,r2,ls,sz,tt,po[S],ln[S],l[N],f[N],ch[N][],hd[N],nx[N],to[N],rt[N],fa[N][];
struct nd {int l,r; pr p;}t[N*];
void ad(int x,int y) {to[++e]=y,nx[e]=hd[x],hd[x]=e;} void ins(int c) {
int u=ls,x=ch[u][c];
if(x) {
if(l[u]+==l[x]) {ls=x; return;}
l[++sz]=l[u]+,f[sz]=f[x],f[x]=sz,ls=sz;
for(int j=;j<;j++) ch[sz][j]=ch[x][j];
for(;u&&ch[u][c]==x;u=f[u]) ch[u][c]=sz;
if(ch[u][c]==x) ch[u][c]=sz;
} else {
for(ls=++sz,l[sz]=l[u]+;u&&!ch[u][c];u=f[u]) ch[u][c]=sz;
int x=ch[u][c];
if(!x) {ch[u][c]=sz; return;}
if(l[u]+==l[x]) {f[sz]=x; return;}
l[++sz]=l[u]+,f[sz]=f[x],f[x]=f[ls]=sz;
for(int j=;j<;j++) ch[sz][j]=ch[x][j];
for(;u&&ch[u][c]==x;u=f[u]) ch[u][c]=sz;
if(ch[u][c]==x) ch[u][c]=sz;
}
} void pu(int x) {t[x].p=max(t[l(x)].p,t[r(x)].p);}
int mrg(int x,int y,int L=,int R=m) {
if(!x||!y) return x|y;
int z=++tt;
if(L==R) {t[z].p=make_pair(t[x].p.first+t[y].p.first,-L); return z;}
l(z)=mrg(l(x),l(y),L,M),r(z)=mrg(r(x),r(y),M+,R),pu(z);
return z;
}
void upd(int &x,int v,int L=,int R=m) {
if(!x) x=++tt;
if(L==R) {t[x].p=make_pair(t[x].p.first+,-v); return;}
if(v<=M) upd(l(x),v,L,M); else upd(r(x),v,M+,R);
pu(x);
}
pr qr(int x,int l,int r,int L=,int R=m) {
if(!x) return make_pair(,);
if(l<=L&&r>=R) return t[x].p;
if(r<=M) return qr(l(x),l,r,L,M); if(l>M) return qr(r(x),l,r,M+,R);
return max(qr(l(x),l,r,L,M),qr(r(x),l,r,M+,R));
} int gt(int x,int ln) {for(int i=;~i;i--) if(l[fa[x][i]]>=ln) x=fa[x][i]; return x;}
void dfs(int x) {for(int i=hd[x];i;i=nx[i]) dfs(to[i]),rt[x]=mrg(rt[x],rt[to[i]]),fa[to[i]][]=x;} int main() {
scanf("%s%d",sr,&m);
for(int i=;i<=m;i++) {
scanf("%s",s),ls=;
for(int j=;s[j];j++) ins(s[j]-'a'),upd(rt[ls],i);
}
for(int i=,u=,s=;sr[i];i++) {
int c=sr[i]-'a';
while(u&&!ch[u][c]) u=f[u],s=l[u];
if(ch[u][c]) ln[i+]=++s,u=ch[u][c],po[i+]=u;
}
for(int i=;i<=sz;i++) ad(f[i],i);
dfs(),scanf("%d",&q);
for(int j=;j<;j++) for(int i=;i<=sz;i++) fa[i][j]=fa[fa[i][j-]][j-];
while(q--) {
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
if(ln[r2]<r2-l2+) {printf("%d 0\n",l1); continue;}
pr k=qr(rt[gt(po[r2],r2-l2+)],l1,r1);
if(k.first) printf("%d %d\n",-k.second,k.first); else printf("%d 0\n",l1);
}
return ;
}

Codeforces 666E Forensic Examination的更多相关文章

  1. Codeforces 666E Forensic Examination SAM or SA+线段树合并

    E. Forensic Examination http://codeforces.com/problemset/problem/666/E 题目大意:给模式串S以及m个特殊串,q个询问,询问S的子串 ...

  2. Codeforces.666E.Forensic Examination(广义后缀自动机 线段树合并)

    题目链接 \(Description\) 给定串\(S\)和\(m\)个串\(T_i\).\(Q\)次询问,每次询问\(l,r,p_l,p_r\),求\(S[p_l\sim p_r]\)在\(T_l\ ...

  3. Codeforces 666E Forensic Examination SAM+权值线段树

    第一次做这种$SAM$带权值线段树合并的题 然而$zjq$神犇看完题一顿狂码就做出来了 $Orz$ 首先把所有串当成一个串建$SAM$ 我们对$SAM$上每个点 建一棵权值线段树 每个叶子节点表示一个 ...

  4. codeforces 666E. Forensic Examination(广义后缀自动机,Parent树,线段树合并)

    传送门: 解题思路: 很坑的一道题,需要离线处理,假如只有一组询问,那么就可以直接将endpos集合直接累加输出就好了. 这里就要将询问挂在树节点上,在进行线段树合并时查询就好了. 代码超级容易写挂的 ...

  5. CodeForces - 666E: Forensic Examination (广义SAM 线段树合并)

    题意:给定字符串S,然后M个字符串T.Q次询问,每次给出(L,R,l,r),问S[l,r]在L到R这些T字符串中,在哪个串出现最多,以及次数. 思路:把所有串建立SAM,然后可以通过倍增走到[l,r] ...

  6. Codeforces 666E Forensic Examination(广义后缀自动机+线段树合并)

    将所有串(包括S)放一块建SAM.对于询问,倍增定位出该子串所在节点,然后要查询的就是该子串在区间内的哪个字符串出现最多.可以线段树合并求出该节点在每个字符串中的出现次数. #include<b ...

  7. CF 666E Forensic Examination 【SAM 倍增 线段树合并】

    CF 666E Forensic Examination 题意: 给出一个串\(s\)和\(n\)个串\(t_i\),\(q\)次询问,每次询问串\(s\)的子串\(s[p_l:p_r]\)在串\(t ...

  8. CF 666E Forensic Examination——广义后缀自动机+线段树合并

    题目:http://codeforces.com/contest/666/problem/E 对模式串建广义后缀自动机,询问的时候把询问子串对应到广义后缀自动机的节点上,就处理了“区间”询问. 还要处 ...

  9. [CF 666E] Forensic Examination

    Description 传送门 Solution 对 \(T[1..m]\) 建立广义后缀自动机,离线,找出代表 \(S[pl,pr]\) 的每个节点,线段树合并. Code #include < ...

随机推荐

  1. Flask 学习 七 用户认证

    使用werkzeug 实现密码散列 from werkzeug.security import generate_password_hash,check_password_hash class Use ...

  2. C++中文件的读写

    C++中文件的读写 在C++中如何实现文件的读写? 一.ASCII 输出 为了使用下面的方法, 你必须包含头文件<fstream.h>(译者注:在标准C++中,已经使用<fstrea ...

  3. OO第一次总结

    第一次作业: 第一次作业的指导书发下来之后我按着上面的步骤一步一步的做了之后发现项目拉下来了,怎么开始码代码呢...然后在舍友的帮助下才知道怎么建包建类,然后对Java的语法又不是很了解,于是就先把C ...

  4. GitHub 上下载单个文件夹

    写代码的一定经常去github上查看.下载一些源码,有时候会想下载一个项目中的一个文件夹里的内容,但是github上只提供了整个项目的下载,而整个项目里东西太多,压缩的文件太大,github的下载速度 ...

  5. xxe漏洞检测及代码执行过程

    这两天看了xxe漏洞,写一下自己的理解,xxe漏洞主要针对webservice危险的引用的外部实体并且未对外部实体进行敏感字符的过滤,从而可以造成命令执行,目録遍历等.首先存在漏洞的web服务一定是存 ...

  6. wyh的数列~(坑爹题目)

    链接:https://www.nowcoder.com/acm/contest/93/K来源:牛客网 题目描述 wyh学长特别喜欢斐波那契数列,F(0)=0,F(1)=1,F(n)=F(n-1)+F( ...

  7. Class-Based-View(CBV)

    我们都知道,Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承.封装.多态).所以Django在后来加入了Class-Based-View.可以让我们用类写V ...

  8. Mego(05) - 创建模型

    Mego框架使用一组约定来基于CLR类来构建模型.您可以指定其他配置来补充和/或覆盖通过约定发现的内容. 这里需要强调的我们EF不同的是框架只支持数据注释的语法来构建模型,后期只有通过其他接口才能更改 ...

  9. 阿里云API网关(12)为员工创建子账号,实现分权管理API:使用RAM管理API

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  10. apigw鉴权分析(1-2)腾讯开放平台 - 鉴权分析

    一.访问入口 http://wiki.open.qq.com/wiki/%E8%85%BE%E8%AE%AF%E5%BC%80%E6%94%BE%E5%B9%B3%E5%8F%B0%E7%AC%AC% ...