NOI2018 你的名字 后缀自动机_线段树合并_可持久化
#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 你的名字 后缀自动机_线段树合并_可持久化的更多相关文章
- UOJ #395 BZOJ 5417 Luogu P4770 [NOI2018]你的名字 (后缀自动机、线段树合并)
NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) http ...
- 洛谷P4770 [NOI2018]你的名字 [后缀自动机,线段树合并]
传送门 思路 按照套路,直接上后缀自动机. 部分分:\(l=1,r=|S|\) 首先把\(S\)和\(T\)的后缀自动机都建出来. 考虑枚举\(T\)中的右端点\(r\),查询以\(r\)结尾的串最长 ...
- 【BZOJ3413】匹配(后缀自动机,线段树合并)
[BZOJ3413]匹配(后缀自动机,线段树合并) 题面 BZOJ 题解 很好的一道题目. 做一个转化,匹配的次数显然就是在可以匹配的区间中,每个前缀的出现次数之和. 首先是空前缀的出现次数,意味着你 ...
- 【CF666E】Forensic Examination(后缀自动机,线段树合并)
[CF666E]Forensic Examination(后缀自动机,线段树合并) 题面 洛谷 CF 翻译: 给定一个串\(S\)和若干个串\(T_i\) 每次询问\(S[pl..pr]\)在\(T_ ...
- CF666E Forensic Examination 广义后缀自动机_线段树合并_树上倍增
题意: 给定一个串 $S$ 和若干个串 $T_{i}$每次询问 $S[pl..pr]$ 在 $Tl..Tr$ 中出现的最多次数,以及出现次数最多的那个串的编号. 数据范围: 需要离线 题解:首先,很常 ...
- 【洛谷4482】Border的四种求法(后缀自动机_线段树合并_链分治)
这题我写了一天后交了一发就过了我好兴奋啊啊啊啊啊啊 题目 洛谷 4482 分析 这题明明可以在线做的,为什么我见到的所有题解都是离线啊 -- 什么时候有机会出一个在线版本坑人. 题目的要求可以转化为求 ...
- 【CF666E】Forensic Examination 广义后缀自动机+倍增+线段树合并
[CF666E]Forensic Examination 题意:给你一个字符串s和一个字符串集合$\{t_i\}$.有q个询问,每次给出$l,r,p_l,p_r$,问$s[p_l,p_r]$在$t_l ...
- 【洛谷4770】 [NOI2018]你的名字(SAM,线段树合并)
传送门 洛谷 Solution 做过的比较玄学的后缀自动机. 果然就像\(Tham\)所讲,后缀自动机这种东西考场考了不可能做的出来的... 考虑如果\(l=1,r=|S|\)的怎么做? 直接建后缀自 ...
- [HEOI2016/TJOI2016]字符串(后缀数组+二分+主席树/后缀自动机+倍增+线段树合并)
后缀数组解法: 先二分最长前缀长度 \(len\),然后从 \(rnk[c]\) 向左右二分 \(l\) 和 \(r\) 使 \([l,r]\) 的 \(height\geq len\),然后在主席树 ...
随机推荐
- ECMAScript prototype的一个疑问。
既然是疑问 当然首先要贴一段代码. 背景: 探究js的原型继承模式. 疑惑:为何person1和person2的prototype 居然是相等的. 附: 1.Object.create(proto, ...
- linux拷贝文件
linux之cp/scp命令+scp命令详解 2011-03-09 17:27:22| 分类: Linux | 标签:linux cp scp commond |字号 订阅 名称:c ...
- 。net内存优化
1.尽量减少和避免不必要的对象 2.优化算法和数据结构 3.采用非托管代码或者模块编写数据处理逻辑 4.NET应用程序的内存一定程度上受垃圾回收的影响.并指出,一些数据结构如List,系统会分配多余的 ...
- codeforces 277 A Learning Languages 【DFS 】
n个人,每个人会一些语言,两个人只要有会一门相同的语言就可以交流,问为了让这n个人都交流,至少还得学多少门语言 先根据n个人之间他们会的语言,建边 再dfs找出有多少个联通块ans,再加ans-1条边 ...
- RabbitMQ学习笔记(1)----RabbitMQ简介与安装
·1. 什么是RabbitMQ? RabbitMQ是流行的开源消息队列系统,用erlang语言开发.RabbitMQ是AMQP(高级消息队列协议)的标准实现. 而AMQP协议则是指:即Advanced ...
- Unity5.X 开发资源介绍
Asset 资源 Category 类别 Publisher 开发商 Rating 评级 Version 版本号 Windows → Asset Store 资源商店 [Ctrl + 9] U ...
- echart的tooltip自定义换行
自定义换行,内容很长的时候 tooltip : { trigger: 'axis', axisPointer : { // 坐标轴指示器,坐标轴触发有效 type : 'shadow' // 默认为直 ...
- ArchLinux出现ACPI ERROR的解决方法
ArchLinux关机.重启时出现ACPI错误: ACPI Error:Method parse/execution failed \_SB.PCI0.PGON,AE_AML_LOOP_TIMEOUT ...
- http://my.oschina.net/joanfen/blog/160156
http://my.oschina.net/joanfen/blog/160156 http://code4app.com/ios/iOS7-Sampler/5254b2186803faba0d000 ...
- 【HDU 6299】Balanced Sequence
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 我们贪心地把每一个括号序列能匹配都按照栈的规则都匹配出来. (直接递增匹配对数*2就可以了 最后栈里面就只剩下类似))))((((( ...