P4770 [NOI2018]你的名字】的更多相关文章

NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) https://www.luogu.org/problemnew/show/P4770 (uoj) http://uoj.ac/problem/395 题解: 其实非常水,转化成\(S[l,r]\)和\(T\)有多少本质不同的公共子串,我们就是要求出串\(T\)每个位置与\(S[l,r]\)最长匹配的长度.…
题目背景 实力强大的小A 被选为了ION2018 的出题人,现在他需要解决题目的命名问题. 题目描述 小A 被选为了ION2018 的出题人,他精心准备了一道质量十分高的题目,且已经把除了题目命名以外的工作都做好了. 由于ION 已经举办了很多届,所以在题目命名上也是有规定的,ION 命题手册规定:每年由命题委员会规定一个小写字母字符串,我们称之为那一年的命名串,要求每道题的名字必须是那一年的命名串的一个非空连续子串,且不能和前一年的任何一道题目的名字相同. 由于一些特殊的原因,小A 不知道IO…
传送门 思路 按照套路,直接上后缀自动机. 部分分:\(l=1,r=|S|\) 首先把\(S\)和\(T\)的后缀自动机都建出来. 考虑枚举\(T\)中的右端点\(r\),查询以\(r\)结尾的串最长可以往左延伸多长,使得它仍然是\(S\)的子串.记该长度为\(lim_r\). \(lim_r\)可以在\(SAM_S\)中瞎跳跳出来. 那么答案即为 \[ \sum_{i=2}^{cnt} \max(0,len_i-\max(len_{fa_i},lim_{pos_i})) \] 其中\(i\)是…
传送门 upd 19.4.24: WC这个做法真的有问题,不往回跳会WA是因为一开始跳到了S[1...l-1]所对应的点,然后往后接字符的时候可能会因为不在正确的endpos中,然后往回跳过头,其实一开始只要从起点开始跳就行了 Orz @Itst ddw 这题写死我了,因为一点点鬼会注意到的细节调好久,,, 先考虑前17个点,如果我们不考虑T的不同子串限制,那么就是把T放在S的SAM上匹配,答案为\(\sum_{i=1}^{|T|}i-l[i]\)(匹配长度).考虑怎么判重,对T也构建一个SAM…
蒟蒻表示不会sam凉凉了,所以只能提高SA技巧? 题意:有一个串\(A\),每次选择一个\(A\)的子串\(A'\),以及串\(B\),问\(B\)的所有本质不同子串中不在\(A'\)中的串的数量. (定义\(A_i\)表示以字符\(A_i\)开头的后缀,\(B_i\)同理) \(B\)的本质不同字串显然是\(|B|*(|B|+1)/2\)了,然后要减去本质不同的在\(A'\)中的串 首先把所有串拼一起,把SA建出来,辣么就可以在SA中找到\(A'\)所对应的所有后缀,对于\(B\)对应的每个后…
传送门 我有种自己根本没学过SAM的感觉……最后还是抄了老半天的题解…… 首先,对$S$和每一次的$T$都建一个SAM 先考虑一下$l=1,r=\left| S \right|$的情况 设$lim_i$表示字符串$T[1..i]$能在$S$中匹配到的最长后缀(即$T[i-lim_i+1,i]$是$S$的子串且$lim_i$最大)(有可能不存在这个字符那么$lim_i=0$) 这个$lim_i$可以不断地在$S$的后缀自动机上跳来求出.当无法向下匹配时,一直跳parent树直到可以匹配为止 我们假…
题目链接: [Noi2018]你的名字 题目大意:给出一个字符串$S$及$q$次询问,每次询问一个字符串$T$有多少本质不同的子串不是$S[l,r]$的子串($S[l,r]$表示$S$串的第$l$个字符到第$r$个字符组成的子串). 首先考虑$l=1,r=|S|$的情况,对$T$串建立后缀自动机,可以知道$T$串本质不同的子串个数就是后缀自动机上每个点的$len[i]-len[pre[i]]$($len[i]$代表这个点所能表示的最长串长度),这也就是后缀自动机上每个点贡献的子串个数.对于每个点…
[BZOJ5417][NOI2018]你的名字(线段树,后缀自动机) 题面 BZOJ 洛谷 题解 首先考虑\(l=1,r=|S|\)的做法,对于每次询问的\(T\)串,暴力在\(S\)串的\(SAM\)上跑,对于每个点记录其被匹配的最大长度,然后把每个被匹配到的点以及它到\(parent\)树根节点的所有节点全部计算一下能够被匹配的最大长度,最后计算一下有多少个串在\(S\)中出现过.拿总方案减去不合法就行了. 然后现在\(l,r\)任意,那么首先线段树合并求出所有的\(endpos\). 一样…
bzoj5417/luoguP4770 [NOI2018]你的名字(后缀自动机+线段树合并) bzoj Luogu 给出一个字符串 $ S $ 及 $ q $ 次询问,每次询问一个字符串 $ T $ 有多少本质不同的子串不是 $ S[l,r] $ 的子串. 题解时间 跟上一道题有点像哈. 只不过这一次是要将 $ T $ 放在 $ S $ 上匹配. 我们先不管每次选取的 $ S $ 段不同,就假设我们已经建好了选取的 $ S $ 段的SAM(也就是前68pts啦) 我们直接把 $ T $ 放上去匹…
题目描述 小A 被选为了ION2018 的出题人,他精心准备了一道质量十分高的题目,且已经把除了题目命名以外的工作都做好了. 由于ION 已经举办了很多届,所以在题目命名上也是有规定的,ION 命题手册规定:每年由命题委员会规定一个小写字母字符串,我们称之为那一年的命名串,要求每道题的名字必须是那一年的命名串的一个非空连续子串,且不能和前一年的任何一道题目的名字相同. 由于一些特殊的原因,小A 不知道ION2017 每道题的名字,但是他通过一些特殊手段得到了ION2017 的命名串,现在小A 有…
看到题目名字去补番是种怎么样的体验 我只会 \(68\) 分,打了个暴力.正解看了一会儿,发现跟 \([HEOI2016/TJOI2016]\) 字符串很像,用线段树合并维护 \(endpos\) 集合,然后一边匹配一边记录答案. \[ans=\sum_{i=1}^{cnt}max(0,len_i-max(len_{fa_i},lim_{pos_i}))\] \(Code\ Below:\) #include <bits/stdc++.h> #define ll long long using…
SAM真让人头秃. 题面 https://www.luogu.org/problemnew/show/P4770 首先考虑 l=1,r=∣S∣的做法 如果对于ION2018的子串不用判重的话,对ION2017建SAM跑一遍就好了. 此时ION2018的每一个前缀对答案的贡献为前缀长度-匹配长度. 考虑怎么去重. 这应该算是SAM比较常用去重的一种套路. 对ION2018建出SAM. 原本就算答案的方式是枚举子串的右端点的位置. 现在改为枚举枚举SAM上的节点. 由于对于每种串要只计算一次. 先计…
Description 小A 被选为了ION2018 的出题人,他精心准备了一道质量十分高的题目,且已经把除了题目命名以外的工作都做好了. 由于ION 已经举办了很多届,所以在题目命名上也是有规定的,ION 命题手册规定:每年由命题委员会规定一个小写字母字符串,我们称之为那一年的命名串,要求每道题的名字必须是那一年的命名串的一个非空连续子串,且不能和前一年的任何一道题目的名字相同. 由于一些特殊的原因,小A 不知道ION2017 每道题的名字,但是他通过一些特殊手段得到了ION2017 的命名串…
讲解在满分做法的博客中 Code: #include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) #define maxn 3000008 #define ll long long #define N 30 using namespace std; int pos[maxn],n,querie…
题解: 前68分非常简单 建立SAM 另一个串在上面跑,然后求一个树链的并 我们会发现暴力就是min(l^2,n)的 所以复杂度最多是nsqrt(n)的 当然我们也可以nlogn维护 把所有点按照dfs序排序,每个点到根的距离减去排序后 相邻两点LCA到根的距离就是树链的并的长度 不过要注意一下由于有权值 所以每个点在当前点可能只取了一部分权值 调试的时候发现 cnt没清空 *** windows下不开O2不会跑到其他数组里,开了O2就会跑到其他数组里 linux下开不开都会跑过去 linux下…
对S建SAM,拿着T在上面跑 跑的时候不仅无法转移要跳parent,转移过去不在范围内也要跳parent(注意因为范围和长度有关,跳的时候应该把长度一点一点地缩) 这样就能得到对于T的每个前缀,它最长的不合法的后缀的长度ill[i] 得到他要去重,以后可以再对T建SAM,然后对于每个节点,$ans+=max(0,len[i]-max(len[fa[i]],ill[pos[i]]))$,其中pos[i]是它的right集合中随便一个位置(因为每个位置的小于len的ill都一样) 那么怎么判在不在范…
题面 rt,如果省选没退役就补 SAM的优势:简单明了 先建S的SAM并标记所有节点,之后每次询问直接把T按广义SAM的方法插上去,统计新加的节点到根的状态代表的本质不同子串数,减掉被标记的部分就是T独有的 #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; ; ],fth[N],len[N],vis[N],ori[N]; i…
传送门 洛谷 Solution 做过的比较玄学的后缀自动机. 果然就像\(Tham\)所讲,后缀自动机这种东西考场考了不可能做的出来的... 考虑如果\(l=1,r=|S|\)的怎么做? 直接建后缀自动机然后跳. 接着就是\(l,r\)随机... 详细说明可点开蓝色题解按钮然后膜拜第一篇题解! 考虑线段树合并,我们关心的其实只有父亲关系和len对吧. 那么维护一下区域有多少个值,然后每一次查询符不符合要求就好了. 代码实现 代码戳这里…
传送门 UPD:发现之前被smy误导的一个细节,改过来之后就AC了-- 一道比较套路的SAM题,虽然我连套路都不会-- 先考虑前\(68pts\),也就是\(l=1 , r=|S|\)的情况.我们对\(S\)建好SAM,把\(T\)扔到\(S\)的SAM上匹配,如果不考虑本质不同子串的性质,那么答案就是\(\sum\limits_{i=1}^{|T|} i - l_i\),其中\(l_i\)是匹配到第\(i\)个字符时的匹配长度. 然后考虑如何去重.对\(T\)也建SAM,把\(T\)也放在\(…
LOJ 洛谷 BZOJ 考虑\(l=1,r=|S|\)的情况: 对\(S\)串建SAM,\(T\)在上面匹配,可以得到每个位置\(i\)的后缀的最长匹配长度\(mx[i]\). 因为要去重,对\(T\)也建SAM,计算上面所有节点的答案.记\(pos[i]\)表示\(i\)节点第一次出现的下标(同一节点代表的串出现的位置集合相同,所以随便记一个即可). 则节点\(i\)的答案为:\(\max(0,\ len[i]-\max(len[fa[i]],\ mx[pos[i]]))\). 考虑\(l,r…
即求b串有多少个本质不同的非空子串,在a串的给定区间内未出现.即使已经8102年并且马上就9102年了,还是要高举SA伟大旗帜不动摇. 考虑离线,将所有询问串及一开始给的串加分隔符连起来,求出SA.对于每个询问,我们对串的每个后缀,求出其在给定区间中最长的lcp是多少.这样就能得到不考虑本质不同时的答案,再考虑该串名次数组中相邻后缀的lcp去一下重即可. 考虑怎么求这个最长的lcp.设该后缀在名次数组中的位置是i,给定区间是[l,r],这个东西实际上就是max{min{lcp(i..j),r-s…
其实很水的一道题吧.... 题意是:每次给定一个串\(T\)以及\(l, r\),询问有多少个字符串\(s\)满足,\(s\)是\(T\)的子串,但不是\(S[l .. r]\)的子串 统计\(T\)本质不同的串,建个后缀自动机 然后自然的可以想到,对于每个\(T\)的子串,它对应了一个\(right\)集合 那么,它应该会被这个\(right\)集合所限制 考虑对于每个\(i\),求出最小的\(l\)使得\(T[l .. i]\)存在于\(S[l..r]\)中 这个可以套个线段树转移 然后就没…
考虑l=1,r=n的68分,对S和T建SAM,对T的SAM上的每个节点,计算它能给答案带来多少贡献. T上节点x代表的本质不同的子串数为mx[x]-mx[fa[x]],然后需要去掉所代表子串与S的最长公共子串的长度. 从1到length(T)扫一遍,SAM基本操作求出每个前缀与S的最长公共子串. 答案为$\sum_{i=1}^{cnt}max(0,mx[x]-max(mx[fa[x]],len[tag[x]]))$,其中tag[x]是x所代表的子串在T中的第一个出现位置,len[i]为T的前缀i…
题目 可能是一个乱搞做法,同时也跪求有人能帮我分析一下复杂度 还是先来看比较简单的\(68pts\),也就是\(l=1,r=|S|\)的情况 我们可以直接把\(S\)串和所有的\(T\)串一起建一个广义\(SAM\),用一个\(vector\)维护每个\(T\)加入\(SAM\)时新产生的节点 我们只需要求出来这些新增节点没有在\(S\)串出现的本质不同的子串个数就好了 我们提前处理好每一个节点的\(endpos\),标记一下其是否在\(S\)中出现过 对于那些新出现在\(SAM\)上的节点\(…
题目: 洛谷4770 UOJ395 分析: 一个很好的SAM应用题-- 一句话题意:给定一个字符串\(S\).每次询问给定字符串\(T\)和两个整数\(l\).\(r\),求\(T\)有多少个本质不同的非空子串不是\(S[l,r]\)的子串. 首先显然是"正难则反",求有多少个本质不同的非空子串是\(S[l,r]\)的子串(下面的"答案"一词指的是这个值).先考虑没有\(l\)和\(r\)限制的情况.分别处理询问.对于\(S\)建出后缀自动机.枚举\(T\)的所有前…
相当复杂的一道题,同样也相当优美.考察的知识点很多:权值线段树的可持久化合并,后缀自动机,后缀树... 考虑 $68pts$  $l=1,r=|s|$的数据:这部分相对好做一些,不过思维难度对我来说已经不小.但是一旦解出这一部分之后离满分算法就不远了.设 ION2017 为 $S$,ION2018 为 $T$.我们想求 $T$ 中出现的子串且在 $S$ 中未出现的种类(即重复的只算一个).直接求未出现的种类似乎有些苦难,我们这么考虑:先求出 $T$ 中的所有种类,再减掉与 $S$ 重合的部分,这…
题意 不妨先考虑\(l=1,r=|S|\)的情况: 这时我们要求的其实是\(S,T\)的本质不同的公共子串数量. 首先对\(S\)建一个后缀自动机,同时对于每个\(T\),我们也建一个自动机. 根据后缀自动机的性质,后缀自动机的所有节点的代表的字符串的集合代表了\(T\)的全部子串,因此我们可以考虑\(T\)后缀自动机的上的每一个点代表的字符串中有多少是和\(S\)的公共子串. 于是考虑怎么求这个东西: 我们对于\(T\)的每一个前缀\(T[1...i]\)求出\(match_i\)表示这个前缀…
先考虑l=1,r=n,并且不要求本质不同的情况.对原串建SAM,将询问串在上面跑,得到每个前缀的最长匹配后缀即可得到答案. 然后考虑本质不同.对询问串也建SAM,统计每个节点的贡献,得到该点right集合中任意一个的匹配长度即可. 然后考虑原问题.我们需要求的仍然只是每个前缀的最长匹配后缀.通过线段树合并得到原串SAM每个点的right集合,同样将询问串在上面跑,跑的时候根据所达点right集合在给定区间中的最大值得到该点极限匹配长度,判断是否能在该点匹配(即极限匹配长度是否不小于该点所表示的最…
题目链接在这里洛谷/LOJ 题目大意 有一个串\(S\),每次询问给你一个串\(T\),两个数\(L\)和\(R\),问你\(T\)有多少个本质不同的子串不是\(S[L,R]\)的子串 SOLUTION 如果你做过生成魔咒和CF1037H,就会做这道题了 有两个坑点: 1.线段树合并时必须每次都新建结点,因为两颗树都得保留 2.每次失配时必须先尝试减小已经匹配的长度,无法继续减少时再跳\(suflink\) 我的大常数代码 #include <algorithm> #include <i…
题目链接 题意简述 给定一个串 \(S\) 多组询问 , 每次给定一个串 \(T\) 和一个 区间 \([l,r]\) 求串\(T\) 有多少个本质不同的子串 满足不是 \(S[l...r]\) 的子串 Sol 首先显然要么 \(SAM\) 要么 \(SA\). 这种带区间还要求本质不同的的一般用 \(SAM\) 好做些吧. 先考虑每次询问的区间就是整个串我们怎么做. 考虑先补集转换,即先求出不合法的子串,然后用总的本质不同子串数减去这个值得到答案. 那么对 \(S\) 和 \(T\) 分别建立…