Brief Description 给定一个字符串, 您需要求出他的严格k小子串或非严格k小子串. Algorithm Design 考察使用后缀自动机. 首先原串建SAM, 然后如果考察每个状态代表的子串的出现次数. 可以知道, 在parent树上某个节点的出现次数就是他的所有儿子的出现次数之和. 所以, 我们可以按照len基数排序, 然后根据这种拓扑序把出现次数计算出来, 同时, 我们也统计出了以某个节点为根的子树的出现次数总和. 有了每个状态的出现次数之后, 我们运行后缀自动机, 每次选择…
[BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. Output 输出仅一行,为一个数字串,为第K小的子串.如果子串数目不足K个,则输出-1 Sample Input aabc 0 3 Sample Output aab HINT N<=5*10…
题目描述 对于一个给定长度为N的字符串,求它的第K小子串是什么. 输入 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. 输出 输出仅一行,为一个数字串,为第K小的子串.如果子串数目不足K个,则输出-1 样例输入 aabc 0 3 样例输出 aab 题解 后缀自动机+dp 先对原串建立后缀自动机,然后在其上面跑dp统计每个节点开始的串的个数. 设f[i]表示与位置i有相同前缀的串…
3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2018  Solved: 662[Submit][Status][Discuss] Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. Output 输出仅…
题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的时间就会爆炸,显然不能暴力连边. 对于前缀不好解决,可以将字符串翻转然后变成判断是否是后缀. 可以发现对于后缀自动机的$parent$树,每个节点是子树内所有节点的后缀. 那么我们可以利用$parent$树来优化建图过程,将树上每个点向子节点连边. 对于每个$A$串和$B$串在后缀自动机上匹配出对应…
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998 题意概述:对于一个给定长度为N的字符串,求它的第K小子串是什么,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.N<=500000,K<=10^9. 应该是有三种做法的(当然后缀树我还没有看),于是就把这个东西当成后缀自动机的板子了(因为它很裸啊!!!). 可以注意到当T=0的时候每走动一步的贡献是1,而T=1的时候每走动一步之后的贡献都是走到的这…
直接构建后缀自动机. 然后. 然后只需要再后缀自动机的go树上类似二分的方法进行查找即可,实际上是“26分”. 然后遇到了处理right集合的问题,然后觉得在go和parent树上上传都是可以的,毕竟一个是向后添加(go),而另一个是向前添加(parent),然后计算出来之后就类似平衡树的查找方式进行查找即可. 然后就A掉了 #include <cstdio> #include <cstring> #include <iostream> #include <alg…
3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2152  Solved: 716[Submit][Status][Discuss] Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. Output 输出仅…
/* 一道在树上乱搞的题目 建立出parent树来, 然后就能搞出每个节点往后能扩展出几个串, 至于位置不同算同一个的话就强制让right集合大小为1即可 然后在树上类比权值线段树找第k大26分统计一下即可 */ #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<iostream> #define ll long long #define…
题目链接 \(Description\) 给定字符串S,求其第K小子串.(若T=0,不同位置的相同子串算1个:否则算作多个) \(Solution\) 建SAM,处理出对于每个节点,它和它的所有后继包含的子串数量sz(自叶子向根枚举转移更新即可),然后在SAM上走. 每次优先看字典序小的边(设会到达v),若sz[v]<K,则K-=sz[v],枚举下一条边:否则K-=A[v],输出这个转移,然后p=v.(是A[v]!是匹配了v节点) 如果T=0,更新时sz[p]的初值为1,A[p]=1:如果T=1…
http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串为前缀的字符串数量和某字符串的出现数量. wa了两次,写题时犯得错误有: 1.使用样例检查出来向下搜索字符串时没有减去字符串本身出现的数量,比如样例中aabc 0 3,不计重复的情况下向下搜索还要多减一下a和aa分别出现的1次: 2.第一次wa检查出来val没有在建自动机的时候赋值,所以T=1的时候…
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3998 相同子串算多个的话,先求好 right ,然后求一个 sm 表示走到这个点之后有几种走法,即把 DAG 上自己能走到的点的 right 都收集起来,可用拓扑序解决. 相同子串算一个的话,给 DAG 上每个节点都赋上一个1,表示走到那个节点的话算一个子串:然后把 DAG 上自己能走到的点的1都收集起来. 然后可按字典序 dfs 这个 DAG ,如果 k 在这个分支里的话就走进去,否则…
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. Output 输出仅一行,为一个数字串,为第K小的子串.如果子串数目不足K个,则输出-1 Sample Input aabc 0 3 Sample Output aab HINT N<=5*10^5 T<2 K<=10^9 Sol…
传送门 解题思路 \(T=0\)时就和SP7258一样,\(T=1\)时其实也差不多,只不过要把每个点原来是\(1\)的权值改为\(Right\)集合的大小. 代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int MAXN = 500005; int k,type,cnt,lst,n,T; int fa[M…
对字符串构建一个后缀自动机. 每次查询的就是在转移边上得到节点的parent树中后缀节点数量. 由于强制在线,可以用动态树维护后缀自动机parent树的子树和. 注意一个玄学的优化:每次在执行连边操作时,让parent节点作为x,新节点作为y,否则在一串字符相同的串会被莫名其妙卡成N方. 压行后的lct和sam #include <cstdio> #include <cstring> #include <map> using namespace std; struct…
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. Output 输出仅一行,为一个数字串,为第K小的子串.如果子串数目不足K个,则输出-1 Sample Input aabc 0 3 Sample Output aab 解题思路: 在后缀自动机Parent树上的每个节点所代表的串都是以祖先…
题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1, len_x]\),方案数就相当于是从\(siz_x\)里面选两个,也就是\(\frac{siz_x (siz_x - 1)}{2}\) 直接拿线段树维护一下,标记永久化一下炒鸡好写~ #include<bits/stdc++.h> #define int long long #define L…
https://blog.csdn.net/WAautomaton/article/details/85057257 解法一:后缀数组 显然将原数组差分后答案就是所有不相交不相邻重复子串个数+n*(n-1)/2. 答案=重复子串个数-相邻或相交重复子串个数. 前者单调栈直接求解,注意细节,重点在后者. 由于是有关相交的计数问题,考虑类似[NOI2016]优秀的拆分的设关键点的做法. 枚举两个串的偏移量k,每k个位置设一个关键点,我们需要保证任意两个相距为k的重复子串都在且仅在它们覆盖的第一个关键…
题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并... 首先可以转化一下模型(想不到qwq):问题可以转化为统计\(B\)中每个前缀在\(A\)中出现的次数.(画一画就出来了) 然后直接对\(A\)串建SAM,线段树合并维护一下siz就行了 #include<bits/stdc++.h> using namespace std; const int MAXN = 4e5 + 10, SS = 1e7 + 10; int N, M; char S[MAXN], T[MAXN];…
题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并 首先对所有的\(t_i\)建个广义后缀自动机,这样可以得到所有子串信息. 考虑把询问离线,然后把\(S\)拿到自动机上跑,同时维护一下最长能匹配的位置,对于每个以\(i\)位置为右端点的询问我们需要找到\(len\)最小的状态满足\(len[sta] >= pr - pl + 1\)(这部分把每个以\(i\)为端点的询问排序后暴力跳即可,复杂度\(O(n \sqrt{n})\)).那么现在的问题就是对于每个状态,如何知道他在每个\…
题意 题目链接 Sol 后缀自动机+线段树 还是考虑通过每个前缀的后缀更新答案,首先出现次数只有一次,说明只有\(right\)集合大小为\(1\)的状态能对答案产生影响 设其结束位置为\(t\),代表的最短/最长后缀的位置为\(l, r\)(l在r的右边) 那么对于区间\(r - l\)内的\(x\)位置,可以用\(t - x+1\)更新答案 对于区间\(l - t\)内的位置,可以用\(l\)更新答案 这两种情况不好一起弄(因为第一种情况肯定要把\(x\)提出来),那么直接开两棵线段树就行了…
题面 传送门 题解 字符串就硬是要和数据结构结合在一起么--\(loj\)上\(rk1\)好像码了\(10k\)的样子-- 我们设\(L=r-l+1\) 首先可以发现对于\(T\)串一定是从左到右,能取就取是最优的 我们先用后缀自动机\(+\)线段树合并求出自动机上每一个节点的\(endpos\)集合.如果\(L\)较大的时候,我们考虑二分找到第一个端点,再找下一个--这样在线段树上找的总次数是\({n\over L}\),复杂度为\(O({n\over L}\log n)\) 但是\(L\)较…
模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合) Code: #include <bits/stdc++.h> using namespace std; #define N 100010 map <int,int> son[N<<1]; char str[N]; int root[N<<1],pla[N],len; int tot=1,last=1,pre[N<<1],dis[N<<1],in[N<<1]…
点此看题面 大致题意: 给你一个字符串\(s\),每次问你一个子串\(s[a..b]\)的所有子串和\(s[c..d]\)的最长公共前缀. 二分 首先我们可以发现一个简单性质,即要求最长公共前缀,则我们必然取\(s[a..b]\)的一个子串\(s[x..b]\),因为求最长公共前缀取长了不会影响答案. 那么如果我们二分答案\(mid\),就变成了每次判断原串第\(c\)个后缀长度为\(mid\)的前缀是否是原串第\(a\sim b-mid+1\)个后缀中某一后缀的前缀. 后缀自动机+线段树合并…
bzoj3879 SvT(后缀自动机+虚树) bzoj 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示),求这些后缀两两之间的LCP(LongestCommonPrefix)的长度之和.一对后缀之间的LCP长度仅统计一遍. 题解时间 bzoj3238 完 全 一 致 只不过这个是只选中其中一部分后缀. bzoj3238可以用SA搞也可以用SAM搞. 这题一样,但是SAM好想. 建完SAM每次询…
bzoj5417/luoguP4770 [NOI2018]你的名字(后缀自动机+线段树合并) bzoj Luogu 给出一个字符串 $ S $ 及 $ q $ 次询问,每次询问一个字符串 $ T $ 有多少本质不同的子串不是 $ S[l,r] $ 的子串. 题解时间 跟上一道题有点像哈. 只不过这一次是要将 $ T $ 放在 $ S $ 上匹配. 我们先不管每次选取的 $ S $ 段不同,就假设我们已经建好了选取的 $ S $ 段的SAM(也就是前68pts啦) 我们直接把 $ T $ 放上去匹…
弦论 bzoj-3998 TJOI-2015 题目大意:给定一个字符串,求其$k$小子串. 注释:$1\le length \le 5\cdot 10^5$,$1\le k\le 10^9$. 想法: 后缀数组傻逼题. 初学后缀自动机我们尝试用后缀自动机解决. 首先先建出$SAM$. 分别考虑$T=0$和$T=1$的情况. 我们处理$f$数组表示以当前节点代表的字符串为前缀的子串个数. 它们俩之间的区别就是$Right$集合的大小. 详情看代码把. 代码: #include <bits/stdc…
传送门 后缀自动机基础题. 求第kkk小的子串(有可能要求本质不同) 直接建出samsamsam,然后给每个状态赋值之后在上面贪心选最小的(过程可以类比主席树/平衡树的查询操作)即可. 代码: #include<bits/stdc++.h> #define ri register int using namespace std; const int N=1e6+5; int n,t,k; char s[N]; struct SAM{ int len[N],link[N],son[N][26],…
题目 对于一个给定长度为N的字符串,求它的第K小子串是什么. 输入格式 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. 输出格式 输出仅一行,为一个数字串,为第K小的子串.如果子串数目不足K个,则输出-1 输入样例 aabc 0 3 输出样例 aab 提示 N<=5*10^5 T<2 K<=10^9 题解 肝了一个中午的论文还是想了好久这种裸题.. 由后缀自动机从根节点…
Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. Output 输出仅一行,为一个数字串,为第K小的子串.如果子串数目不足K个,则输出-1 Sample Input aabc 0 3 Sample Output aab HINT N<=5*10^5 T<2 K<=10^9 思路 看…