这个是满分做法, 68pts 做法在上一篇博客中 
会 68 pts 做法后就十分简单了,只要来一遍线段树合并 right 集合并在匹配的时候判一下是否在 $[l,r]$ 区间中即可
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 5000000
#define N 30
#define ll long long
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
using namespace std; char str[maxn],ss[maxn];
int str_len,ss_len;
int nodes;
int C[maxn],rk[maxn];
int rt[maxn];
int pos[maxn],mx[maxn]; struct Segment_Tree{ int l,r,sumv; }node[maxn<<2];
int newnode(){ return ++nodes; }
void modify(int p,int l,int r,int &o){
if(!o) o=newnode();
++node[o].sumv;
if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) modify(p,l,mid,node[o].l);
else modify(p,mid+1,r,node[o].r);
}
int merge(int x,int y){
if(!x||!y) return x+y;
int o=newnode();
node[o].sumv=node[x].sumv+node[y].sumv;
node[o].l=merge(node[x].l,node[y].l);
node[o].r=merge(node[x].r,node[y].r);
return o;
}
int query(int l,int r,int L,int R,int o){
if(l>r||r<L||l>R) return 0;
if(l>=L&&r<=R) return node[o].sumv;
int mid=(l+r)>>1,res=0;
if(node[o].l) res+=query(l,mid,L,R,node[o].l);
if(node[o].r) res+=query(mid+1,r,L,R,node[o].r);
return res;
} struct SAM{
int last,tot,dis[maxn],ch[maxn][N],f[maxn],pos[maxn];
void init() { last=++tot; }
void ins(int c,int y,int z,int rot){
int p=last,np=++tot; last=np; dis[np]=dis[p]+1; pos[np] = z;
while(p&&!ch[p][c])ch[p][c]=np,p=f[p];
if(!p) f[np]=rot;
else{
int q=ch[p][c],nq;
if(dis[q]==dis[p]+1) f[np]=q;
else{
nq=++tot;
dis[nq]=dis[p]+1;
pos[nq] = pos[q];
memcpy(ch[nq],ch[q],sizeof(ch[q]));
f[nq]=f[q],f[q]=f[np]=nq;
while(p&&ch[p][c]==q) ch[p][c]=nq,p=f[p];
}
}
if(y) modify(y,1,str_len,rt[np]);
}
void build_S1(){
for(int i=1;i<=tot;++i) C[dis[i]]++;
for(int i=1;i<=tot;++i) C[i]+=C[i-1];
for(int i=1;i<=tot;++i) rk[C[dis[i]]--]=i;
for(int i=tot;i>=1;--i) {
int p=rk[i];
rt[f[p]] = merge(rt[f[p]],rt[p]);
}
}
}S1,S2; int main(){
//setIO("input");
scanf("%s",str+1),str_len=strlen(str+1),S1.init();
for(int i=1;i<=str_len;++i) S1.ins(str[i]-'a',i,0,1);
S1.build_S1();
int queries,l,r,st,ed;
scanf("%d",&queries);
while(queries--) { S2.init(),st=S2.tot,scanf("%s%d%d",ss+1,&l,&r),ss_len=strlen(ss+1); for(int i=1;i<=ss_len;++i) S2.ins(ss[i]-'a',0,i,st); ed=S2.tot; int cnt=0,p=1;
long long ans = 0; for(int i=1;i<=ss_len;++i) {
int c=ss[i]-'a';
while(1){
if(S1.ch[p][c] && query(1,str_len,l+cnt,r,rt[S1.ch[p][c]]))
{
++cnt,p=S1.ch[p][c]; break;
}
else {
if(!cnt) {p=1;break; }
--cnt;
if(cnt==S1.dis[S1.f[p]]) p=S1.f[p];
}
}
mx[i]=cnt;
} for(int i=st;i<=ed;++i)
ans+=max(0,S2.dis[i]-max(mx[S2.pos[i]],S2.dis[S2.f[i]]));
printf("%lld\n",ans);
}
return 0;
}

  

NOI2018 你的名字 后缀自动机_线段树合并_可持久化的更多相关文章

  1. UOJ #395 BZOJ 5417 Luogu P4770 [NOI2018]你的名字 (后缀自动机、线段树合并)

    NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) http ...

  2. 洛谷P4770 [NOI2018]你的名字 [后缀自动机,线段树合并]

    传送门 思路 按照套路,直接上后缀自动机. 部分分:\(l=1,r=|S|\) 首先把\(S\)和\(T\)的后缀自动机都建出来. 考虑枚举\(T\)中的右端点\(r\),查询以\(r\)结尾的串最长 ...

  3. 【BZOJ3413】匹配(后缀自动机,线段树合并)

    [BZOJ3413]匹配(后缀自动机,线段树合并) 题面 BZOJ 题解 很好的一道题目. 做一个转化,匹配的次数显然就是在可以匹配的区间中,每个前缀的出现次数之和. 首先是空前缀的出现次数,意味着你 ...

  4. 【CF666E】Forensic Examination(后缀自动机,线段树合并)

    [CF666E]Forensic Examination(后缀自动机,线段树合并) 题面 洛谷 CF 翻译: 给定一个串\(S\)和若干个串\(T_i\) 每次询问\(S[pl..pr]\)在\(T_ ...

  5. CF666E Forensic Examination 广义后缀自动机_线段树合并_树上倍增

    题意: 给定一个串 $S$ 和若干个串 $T_{i}$每次询问 $S[pl..pr]$ 在 $Tl..Tr$ 中出现的最多次数,以及出现次数最多的那个串的编号. 数据范围: 需要离线 题解:首先,很常 ...

  6. 【洛谷4482】Border的四种求法(后缀自动机_线段树合并_链分治)

    这题我写了一天后交了一发就过了我好兴奋啊啊啊啊啊啊 题目 洛谷 4482 分析 这题明明可以在线做的,为什么我见到的所有题解都是离线啊 -- 什么时候有机会出一个在线版本坑人. 题目的要求可以转化为求 ...

  7. 【CF666E】Forensic Examination 广义后缀自动机+倍增+线段树合并

    [CF666E]Forensic Examination 题意:给你一个字符串s和一个字符串集合$\{t_i\}$.有q个询问,每次给出$l,r,p_l,p_r$,问$s[p_l,p_r]$在$t_l ...

  8. 【洛谷4770】 [NOI2018]你的名字(SAM,线段树合并)

    传送门 洛谷 Solution 做过的比较玄学的后缀自动机. 果然就像\(Tham\)所讲,后缀自动机这种东西考场考了不可能做的出来的... 考虑如果\(l=1,r=|S|\)的怎么做? 直接建后缀自 ...

  9. [HEOI2016/TJOI2016]字符串(后缀数组+二分+主席树/后缀自动机+倍增+线段树合并)

    后缀数组解法: 先二分最长前缀长度 \(len\),然后从 \(rnk[c]\) 向左右二分 \(l\) 和 \(r\) 使 \([l,r]\) 的 \(height\geq len\),然后在主席树 ...

随机推荐

  1. 安卓input框获取焦点时,底部按钮会顶上去的解决方法

    var h = document.body.scrollHeight;window.onresize = function(){ if (document.body.scrollHeight < ...

  2. Android 中的View与ViewGroup

    Android重点知识--View和ViewGroup与自定义控件 作者:丁明祥 邮箱:2780087178@qq.com 一.基础 ViewGroup 参考资料: Android 手把手教您自定义V ...

  3. RecyclerView的刷新和加载更多

    1.RecyclerView :出现也不知道多久了,没怎么使用过,上次写的笔记乱七八糟的,再次仔细的整理下.   使用需加入依赖  compile 'com.android.support:recyc ...

  4. ZBrush中如何对模型进行减面操作

    Decimation Master是ZBrush 4R8自带的一个插件.中文名叫减面大师.其功能非常强大,也非常的方便,可以帮助我们提高效率,减少电脑资源损耗.作为一名3D美术师是必须掌握的一个技术. ...

  5. 如何打印枚举类型:%d

    #include <stdio.h> typedef enum SessionState { SESSION_OPENING, /* Session scope is being crea ...

  6. 编写python代码获取4k高清壁纸

    Huskiesir最近在研究python爬虫大约俩周了吧,由于比较懒,也没把具体研究的过程与经验写下来,实在是一大憾事.这次直接上干货,代码送给大家: import re import request ...

  7. [luogu] P2519 [HAOI2011]problem a (贪心)

    P2519 [HAOI2011]problem a 题目描述 一次考试共有n个人参加,第i个人说:"有ai个人分数比我高,bi个人分数比我低."问最少有几个人没有说真话(可能有相同 ...

  8. dockerfile centos+jdk+时区设置

    1.参考博客:https://blog.csdn.net/yjk13703623757/article/details/68944549 2.dockerfile如下 # Base os image ...

  9. 监控Apache计数器

  10. Error: Password file read access must be restricted: /etc/cassandra/jmxremote.password

    在配置JMX远程访问的时候,设置jmxremote.password文件权限,修改该文件时添加写权限,chmod +w jmxremote.password ,放开角色信息那俩行的注释,保存,再使用c ...