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\),然后在主席树 ...
随机推荐
- SwipeRefreshLayout实现下拉刷新上滑加载
1. 效果图 2.RefreshLayout.java package myapplication.com.myapplication; import android.content.Context; ...
- Android ImageView 替换图片
网上找了半天,找到的都是错的,都不是我想要的效果.我想要的是点击一个图片后,图片被替换. 通过一下方法可以实现:“v”是ImageView对象,“image_name”是替换后的图片资源 ((Imag ...
- Win7 disk.sys无法加载的问题
Win7突然无法启动,应该说是启动中卡死,没有别的问题,用安全模式,显示加载disk.sys时卡死.搜索发现很多人遇到这个问题. 实际解决方法是查看数据线,重新插拔,换口,换线. 数据线出现故障往往表 ...
- NSPort与NSRunloop的关系是流与消息调度的关系
NSPort与NSRunloop的关系是流与消息调度的关系. NSPort 将流插入到消息调度队列: 相当于 Socket将流插入到应用一样 - (void)launchThread { NSPort ...
- NGUI 使用Grid自动排列UI
1,NGUI->Create Grid 2,把需要排列的UI放到Grid下边,对Grid进行参数设置
- Codeforces Round #506 (Div. 3) D-F
Codeforces Round #506 (Div. 3) (中等难度) 自己的做题速度大概只尝试了D题,不过TLE D. Concatenated Multiples 题意 数组a[],长度n,给 ...
- UVALive-7198 Tall orders 微积分 二分
题目链接:https://cn.vjudge.net/problem/UVALive-7198 题意 有悬链线方程$ f(x)=a \cdot cosh(\frac{s}{a}) $, 现有两个电线杆 ...
- HDU 4630 No Pain No Game (线段树+离线)
题目大意:给你一个无序的1~n的排列a,每次询问[l,r]之间任取两个数得到的最大gcd是多少 先对所有询问离线,然后把问题挂在区间的左端点上(右端点也行) 在预处理完质数,再处理一个next数组,表 ...
- sql where条件子句
where中可用的运算符: where 的执行 是从右到左: where的SQL优化:(where条件特别多的情况下,效果明显) 对于and,应该尽量把假的放到右边. 对于or,应该尽量把真的放到右边 ...
- 简单实现双向数据绑定mvvm。