P4770:你的名字(SAM、线段树合并)

文章目录

  • 前言
  • 解析

前言

1000A快乐!!!awa
没有想象中的那么恶心。

解析

先考虑每次都询问 [1,n][1,n][1,n] 如何做。
正难则反,用T所有本质不同串数量减去是S串子串又是T的子串的数量
前者很好求,关键是后者
首先可以常规操作求出每个T的前缀在S上匹配的最长后缀长度 www
考虑对T也建出一个SAM,让T在自己的SAM上跑
假设跑到第 iii 个字符,处于结点 uuu
wi≤lenlinkuw_i\le len_{link_u}wilenlinku,说明在 uuu 结点的等价类集合中没有任何子串是S的子串,那么直接往 linklinklink 跳即可,不断上跳,直到不满足这个条件
然后,令 ansu←max⁡(ansu,wi)ans_u\gets \max(ans_u,w_i)ansumax(ansu,wi)
最后匹配子串的总和就是 ∑(ansi−lenlinki)\sum (ans_i-len_{link_i})(ansilenlinki)

考虑有区间限制 [l,r][l,r][l,r]
发现其实后面对于T的SAM的操作是不影响的,唯一的不同就是 www 不太好求了
考虑对S的SAM的每个结点建一棵线段树,存储 endpos⁡\operatorname{endpos}endpos 集合
dfs 一遍线段树合并就可以求出来
(注意这里需要保留原有的线段树,需要可持久化)
然后我们继续常规操作,在S的串上跑T试图求出 wiw_iwi
但是现在的答案还要与 max⁡i∈endposu⁡,i≤ri−l+1\max_{i\in \operatorname{endpos_u},i\le r}i-l+1maxiendposu,iril+1 取个 min
(也就是合法右端点左侧最大的endpos,可以通过刚才建出的线段树查询)

那么我们再匹配之余看看往父亲跳是否可以不劣,如果不劣就往上,这样就可以了

注意跳父亲的条件是不劣而不是更优,因为可能需要跳多次 linklinklink 才能跳到最优解,在此之前结果不变

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e6+100;
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}int m;#define mid ((l+r)>>1)
struct tree{int ls,rs,mx;
};
struct Segment_tree{tree tr[N<<5];int rt[N],tot;inline int copy(int x){tr[++tot]=tr[x];return tot;}inline void pushup(int k){tr[k].mx=max(tr[tr[k].ls].mx,tr[tr[k].rs].mx);return;}void upd(int &k,int l,int r,int p){if(!k) k=copy(0);if(l==r){tr[k].mx=l;return;}if(p<=mid) upd(tr[k].ls,l,mid,p);else upd(tr[k].rs,mid+1,r,p);pushup(k);}int merge(int x,int y,int l,int r){if(!x||!y) return x|y;if(l==r) return x;int now=copy(x);tr[now].ls=merge(tr[now].ls,tr[y].ls,l,mid);tr[now].rs=merge(tr[now].rs,tr[y].rs,mid+1,r);pushup(now);return now;}int ask(int k,int l,int r,int x,int y){if(!k) return 0;if(x<=l&&r<=y) return tr[k].mx;int res(0);if(x<=mid) res=max(res,ask(tr[k].ls,l,mid,x,y));if(y>mid) res=max(res,ask(tr[k].rs,mid+1,r,x,y));return res;}
}t;struct node{int len,fa;int tr[26];
};
struct SAM{char s[N];int n;node st[N];int cnt[N],id[N],pl[N];ll sum[N];int tot=1,lst=1;inline void clear(){while(tot){st[tot].len=st[tot].fa=0;memset(st[tot].tr,0,sizeof(st[tot].tr));sum[tot]=0;--tot;}tot=lst=1;return;}inline void ins(int c,int o){c-='a';int cur=++tot,p=lst;lst=tot;st[cur].len=st[p].len+1;pl[cur]=o;for(;p&&!st[p].tr[c];p=st[p].fa) st[p].tr[c]=cur;if(!st[p].tr[c]) st[cur].fa=1;else{int q=st[p].tr[c];if(st[q].len==st[p].len+1) st[cur].fa=q;else{int pp=++tot;st[pp]=st[q];st[pp].len=st[p].len+1;st[q].fa=st[cur].fa=pp;for(;p&&st[p].tr[c]==q;p=st[p].fa) st[p].tr[c]=pp;}}}void calc(){fill(cnt,cnt+1+n,0);for(int i=1;i<=tot;i++) ++cnt[st[i].len];for(int i=1;i<=n;i++) cnt[i]+=cnt[i-1];for(int i=tot;i>=1;i--) id[cnt[st[i].len]--]=i;for(int i=tot;i>=1;i--){if(id[i]!=1) sum[id[i]]=1;for(int j=0;j<26;j++) sum[id[i]]+=sum[st[id[i]].tr[j]];}return;}void build(){scanf(" %s",s+1);n=strlen(s+1);for(int i=1;i<=n;i++) ins(s[i],i);return;}void print(){for(int i=1;i<=tot;i++)printf("i=%d fa=%d len=%d sum=%lld pl=%d\n",i,st[i].fa,st[i].len,sum[i],pl[i]);}
}s1,s2;vector<int>v[N];
int ans[N];
void dfs(int x){if(s1.pl[x]){t.upd(t.rt[x],1,s1.n,s1.pl[x]);}for(int to:v[x]){dfs(to);t.rt[x]=t.merge(t.rt[x],t.rt[to],1,s1.n);}// printf("x=%d mx=%d\n",x,t.tr[t.rt[x]].mx);return;
}int L,R;
inline int lenth(int x,int val){return max(0,min(min(val,s1.st[x].len),t.ask(t.rt[x],1,s1.n,1,R)-L+1));
}
void work(){s2.build();s2.calc();L=read();R=read();// s2.print();int p1=1,p2=1,now(0);for(int i=1;i<=s2.n;i++){int c=s2.s[i]-'a';while(p1>1&&!s1.st[p1].tr[c]) p1=s1.st[p1].fa,now=s1.st[p1].len;if(s1.st[p1].tr[c]){p1=s1.st[p1].tr[c];++now;}//printf("  p1=%d now=%d\n",p1,now);while(p1>1&&lenth(s1.st[p1].fa,now)>=lenth(p1,now)){//printf("  jump: ask=%d mx=%d rt=%d (%d %d) (%d %d)\n",// t.ask(t.rt[p1],1,s1.n,1,R),t.tr[t.rt[p1]].mx,t.rt[p1],1,s1.n,1,R);p1=s1.st[p1].fa;}now=lenth(p1,now);p2=s2.st[p2].tr[c];while(p2>1&&s2.st[s2.st[p2].fa].len>=now) p2=s2.st[p2].fa;ans[p2]=max(ans[p2],now);//printf("i=%d p1=%d p2=%d now=%d\n",i,p1,p2,now);}for(int i=s2.tot;i>=1;i--){int f=s2.st[s2.id[i]].fa;ans[s2.st[s2.id[i]].fa]=max(ans[f],min(s2.st[f].len,ans[s2.id[i]]));}ll res=s2.sum[1];//printf("tot=%lld\n",res);for(int i=2;i<=s2.tot;i++){//printf("i=%d ans=%d\n",i,ans[i]);res-=max(0,ans[i]-s2.st[s2.st[i].fa].len);ans[i]=0;}printf("%lld\n",res);s2.clear();
}signed main(){
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifs1.build();//s1.print();for(int i=1;i<=s1.tot;i++) v[s1.st[i].fa].push_back(i);dfs(1);m=read();while(m--) work();return 0;
}
/*
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DotNetty 实现 Modbus TCP 系列 (一) 报文类

Modbus TCP/IP 报文报文最大长度为 260 byte (ADU 7 byte MBAP Header 253 byte PDU)Length Unit Identifier 长度 PDU 长度MBAP HeaderPDUPDU 由两部分构成&#xff1a;Function Code(功能码) 和 Data 组成Function Code部分功能码&#xff1a;报文类ModbusHeaderModbusHe…

AT2377-[AGC014E]Blue and Red Tree【启发式合并】

正题 题目链接:https://www.luogu.com.cn/problem/AT2377 题目大意 有两棵树T1,T2T_1,T_2T1​,T2​。T1T_1T1​树上的边开始时都是蓝色的&#xff0c;我们每次选择一条蓝色边路径(x,y)(x,y)(x,y)&#xff0c;然后删掉路径上一条边&#xff0c;连接一条xxx到yyy的红色边。 要…

B - A Funny Bipartite Graph

B - A Funny Bipartite Graph 题意&#xff1a; 一个二分图&#xff0c;左右各有n个点&#xff0c;左边第i个点有一个属性mi&#xff0c;它在一个图中的价值为midi,其中di为它在图中的度数(特殊的&#xff0c;如果度数为0&#xff0c;则价值为0)&#xff0c;求一个该二分图的…

专题突破三之并查集Ⅰ——Portal,parity,食物链,程序自动分析,Almost Union-Find,洞穴勘测

文章目录Portalparity[NOI2001] 食物链程序自动分析UVA11987 Almost Union-Find[SDOI2008] 洞穴勘测Portal source 百度翻译简直就是个鬼…(((m -__-)m 离线 将边和询问按权值排序&#xff0c;指针&#xff0c;将所有权值不超过当前询问iii的边全加进去 答案路径自然是不连…

C# 未来新特性:静态委托和函数指针

C# 每发布一次新版本&#xff0c;都会增加一些底层相关的新特性&#xff0c; 这些特性对大多数商业程序来说并没什么实际用处&#xff0c;主要用于那些对性能有很高要求的代码&#xff0c;如图形处理、机器学习以及数学工具包&#xff0c;等等。接下来的两个提案&#xff0c;主…

CF700E Cool Slogans(SAM,dp)

解析 好题。 首先&#xff0c;我们每次都令 sis_isi​ 是 si1s_{i1}si1​ 的后缀&#xff0c;肯定是不劣的 问题就可以转化到 fail 树上了 首先肯定要线段树合并处理出endpos集合 朴素想法&#xff1a;设父亲 fafafa 的结束位置为 posfapos_{fa}posfa​&#xff0c;若 [posfa−…

pjudge#21651-[PR #4]猜猜看【交互】

正题 题目链接:http://pjudge.ac/problem/21651 题目大意 有一个1∼n1\sim n1∼n的排列&#xff0c;每次你可以询问 iii和jjj的大小关系i,j,ki,j,ki,j,k的中位数 现在要求在222次111操作和2n2n2n次222操作内得到这个排列。 50≤n≤510550\leq n\leq 5\times 10^550≤n≤5105…

JavaWeb --第一章Web基本概念

JavaWeb --第一章Web基本概念 文章目录基本概念前言web开发&#xff1a;web应用程序静态web动态webweb服务器技术讲解web服务器基本概念 前言 web开发&#xff1a; web&#xff0c;网页的意思静态web a. html&#xff0c;css b. 提供给所有人看的数据始终不会发生改变动态we…

DotNetty 实现 Modbus TCP 系列 (二) ModbusFunction 类图及继承举例

DotNetty 实现 Modbus TCP 系列 (一) 报文类ModbusFunction 类图如下&#xff1a;如前文所述&#xff0c;所有请求/相应的 PDU 均继承自 ModbusFunction&#xff0c;其子类传入对应的 Function Code 并实现三个方法&#xff1a;CalculateLength&#xff1a;Data 部分的长度(该方…

AT2366-[AGC012F]Prefix Median【dp】

正题 题目链接:https://www.luogu.com.cn/problem/AT2366 题目大意 有一个长度为2n−12n-12n−1的序列aaa&#xff0c;你可以将其重新排列&#xff0c;定义bib_ibi​为a1∼2i−1a_{1\sim 2i-1}a1∼2i−1​的中位数。 询问有多少种不同的可能的bbb序列。 1≤n≤501\leq n\leq…

专题突破三之并查集Ⅱ——星球大战,In Touch,方格染色,Junk-Mail Filter,关押罪犯,Silver Woods,Must Be Rectangular!

文章目录[JSOI2008]星球大战In Touch方格染色Junk-Mail Filter[NOIP2010 提高组] 关押罪犯Silver WoodsMust Be Rectangular![JSOI2008]星球大战 source 非常套路的&#xff0c;正着打击星球&#xff0c;逆着就是添加星球以及关系&#xff0c;并查集维护此时连通块个数 就是…

模板:整体二分

所谓整体二分&#xff0c;就是对整体进行二分 &#xff08;逃&#xff09; 前言 又是一个狂艹树套树的小清新分治算法 但是树套树不需要动脑啊 整体二分有一些比较重要的条件&#xff1a; 修改对判定答案的贡献互相独立&#xff0c;修改之间互不影响效果修改如果对判定答案有…

JavaWeb --第二章 Tomact详情

JavaWeb --第二章 Tomact详情 文章目录Tomcat安装TomcatTomcat启动和配置配置发布一个web网站Tomcat 安装Tomcat 去官方下载 https://tomcat.apache.org Tomcat启动和配置 文件夹作用&#xff1a; 启动/关闭 Tomcat&#xff1a; 文件夹bin/startup.bat 开启 网址&#x…

P8352-[SDOI/SXOI2022]小N的独立集【dp套dp】

正题 题目链接:https://www.luogu.com.cn/problem/P8352 题目大意 给出一棵树&#xff0c;每个点的权值是[1,k][1,k][1,k]之间的一个数&#xff0c;对于i∈[1,nk]i\in[1,nk]i∈[1,nk]求令这棵树的最大独立集权值为iii的方案数。 1≤n≤1000,1≤k≤51\leq n\leq 1000,1\leq k\…

开源的类似于Apache ab的压力测试命令行工具SuperBenchmarker

SuperBenchmarker 是ㄧ个开源的类似于Apache ab的压力测试命令行工具。可以在 .NET 4.52 或者 .NET Core 2.0 平台上运行。可支持Get、Post、Put、Delete这些调用方式&#xff0c;调用时能指定Concurrent user、Request数、Header template…等。可以从Github、Chocolatey这两种…

CodeForces:643(VK cup)

文章目录前言CF643A Bear and ColorsDescription\text{Description}DescriptionSolution\text{Solution}SolutionDescription\text{Description}DescriptionCF643B Bear and Two PathsDescription\text{Description}DescriptionSolution\text{Solution}SolutionCode\text{Code}…

一二三系列之优先队列、st表——Battle,Heapsort,A Magic Lamp

文章目录BattleHeapsortA Magic LampBattle source 如果怪兽先死&#xff0c;那么英雄血量不足也没关系 反悔贪心 每次都先杀怪兽再说&#xff0c;如果血量不够了&#xff0c;就倒回去从怪兽打出伤害由高到低反悔&#xff0c;选择抵御或者加血&#xff0c;肯定哪个加的更多…

JavaWeb --第三章 HTTP协议详解

JavaWeb --第三章 HTTP协议详解 Http 什么是HTTP HTTP&#xff1a; 超文本传输协议&#xff08;Hypertext Transfer Protocol&#xff0c;HTTP&#xff09;是一个简单的请求-响应协议&#xff0c;它通常运行在TCP之上。 文本&#xff1a;html&#xff0c;字符串&#xff0c…

AT2382-[AGC015D]A or...or B Problem

正题 题目链接:https://www.luogu.com.cn/problem/AT2382 题目大意 询问在[L,R][L,R][L,R]中选取一个或多个数&#xff0c;将它们按位或后能得到多少种不同的结果。 1≤L≤R<2601\leq L\leq R<2^{60}1≤L≤R<260 解题思路 我们先把高位的LLL和RRR都有的111都删除&a…

数据结构一【树状数组】普通、二维、离线树状数组的(单点修改,单点查询,区间修改,区间查询)模板及应用例题总结

文章目录树状数组lowbit线段树与树状数组单点修改区间查询区间修改区间求和二维树状数组离线树状数组例题POJ&#xff1a;starsMooFest[SDOI2009]HH的项链Turing TreeCounting SequencesZip-line树状数组 用于快速高效的计算与前缀和相关的信息 lowbit int lowbit( int i ) …