1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1383  Solved: 582[Submit][Status][Discuss] Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过. 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所…
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1153  Solved: 482[Submit][Status][Discuss] Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过. 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所…
将字符串翻转后接到原串的后面,中间加一个分隔符,每次都贪心选择rankrank小的那个 事实上就是练习一发后缀数组的模板 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<vector> #include<cstdio> #include<queue> #include<cmath> #incl…
[BZOJ1692][Usaco2007 Dec]队列变换 Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过. 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie.Sylvia.Dora,登记人员就把这支队伍登记为BSD…
跟BZOJ 4278: [ONTAK2015]Tasowanie一模一样 SA的做法就是把原串倒过来接在原串后面,O(nlogn)O(nlogn)O(nlogn)做后缀数组,就能O(1)O(1)O(1)够比较每个前缀和后缀谁的字典序小了. Hash二分也可以. CODE(SA) O(nlogn)O(nlogn)O(nlogn) #include<bits/stdc++.h> using namespace std; char cb[1<<15],*cs=cb,*ct=cb; #de…
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1692 题意: 给出一个长度为N的字符串,每次可以从串头或串尾取一个字符,添加到新串中,使新串的字典序最小. 做法: 经过推导(略),发现只要贪心地取两端字典序较小的一端,所以在一开始对所有的正反后缀排序,即把原串倒过来接在后面求一遍SA就行了. 写了个倍增求SA[]+height[]的板子,代码可能比较长,但相对来说可能容易理解一点... #include <bits/stdc++.h>…
http://www.lydsy.com/JudgeOnline/problem.php?id=1692 http://www.lydsy.com/JudgeOnline/problem.php?id=1640 很显然,我们取两边时,要取向右(左)拓展得到最小的(相同的情况下),如果不相同,显然取越小的越好. 那么我们需要用后缀数组来加速判断向右(左)拓展时的最小. (ps:后缀数组的c数组一定要开大,我之前逗了,..) #include <cstdio> #include <cstri…
---恢复内容开始--- 题目链接:BZOJ - 1692 题目分析 首先,有个比较简单的贪心思路:如果当前剩余字符串的两端字母不同,就选取小的字母,这样显然是正确的. 然而若两端字母相同,我们怎么选取呢? 这时我们要从两端分别向内部比较,看那一端向内的字符串字典序小. 比如这个字符串 ABCDBA,从左端向内是 ABC.. 从右端向内是 ABD... 所以就选取左端的字符. 这样直接比较是 O(n^2) 的,我们可以使用后缀数组的 Rank 数组来比较. 我们在字符串后加上分隔符,然后再将字符…
Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过. 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie.Sylvia.Dora,登记人员就把这支队伍登记为BSD).登记结束后,组委会将所有队伍的登记名称按字典序升序排列,…
Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in", "r", stdin) #define maxn 4000000 using namespace std; int n, m, tot; int arr[maxn], height[maxn], A[maxn]; namespace SA { int rk[maxn], tp[maxn], sa[maxn], tax[maxn]…
题目大意 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T.\(len \leq 200000\) 题解 我们从归并排序的角度去想,每次把两者之一较小的取出来 遇到相等的元素的时候,排序时取那个都是一样的. 但是在这道题中我们是求字典序最小,这就不一样了. 我们不能任意取,这一步的决策其实是由后面的数字的大小决定的 怎么说呢... 方法蕴藏在这三张图里了,自己去悟吧. 黑色箭头表示选取,黑色圆圈表示确定选取序列的理由. 迭代第一次 迭代第二次 迭代第三次…
题目大意: 给定n个字符串连成了一篇文章,问每个字符串在这篇文章中出现的次数,可重复覆盖 这里ac自动机和后缀数组都可以做 当然后缀数组很容易就解决,但是相对时间消耗高 这里就只讲ac自动机了 将每个字符串放入ac自动机中,这里需要记录到达每个ac自动机上的节点出现这个状态有多少次 而我们添加字符串进入的时候,应该是把经过的每个节点的val都++,说明这个字符串多出现了一次这个值 然后因为自己用字符串在ac自动机上走肯定是到达离root最近的点,也就是说有很多的点会不断通过fail指针指向他,而…
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想到对后缀求height,也就是用 后缀数组+单调栈 维护一段\(height\)相同的区间,单调栈中的\(height\)递增,顺便维护区间最小值(有负数).最大值.元素个数. (然后我就不会写了...) 每次弹出区间时,计算该区间右端点和后面的点与该区间内的点的答案(该区间内的点作为右端点的答案已…
这题可以用回文自动机来做,但是我并没有学,于是用Manacher+SA的做法O(nlogn)水过 首先,看到回文串就能想到用Manacher 同样还是要利用Manacher能不重复不遗漏地枚举每个回文子串的性质 只是不重复不遗漏还不够,我们还要统计出现次数 每个子串一定是一个后缀的前缀,于是可以用后缀数组 用后缀数组求出height数组之后,对于在Manacher过程中枚举到的每个长度为k的回文串,可以在height数组中二分,用O(logn)的时间求出这个子串的出现次数 BZOJ和COGS上有…
题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个串的长度>=x, 但据说有一种高端做法是把二分换成单调队列,能减少常数,可惜我并没有看懂...... 原题好像是哈希的骚操作,但网上的题解好像都是后缀数组...... 比上一道男人八题简单多了,我原来的错代码竟然卡过去了70分.. #include <cstdio> #include <…
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainbow 调制了 nn 杯鸡尾酒.这 nn 杯鸡尾酒排成一行,其中第 ii 杯酒 (1≤i≤n1≤i≤n) 被贴上了一个标签 sisi,每个标签都是 2626 个小写英文字母之一.设 Str(l,r)Str(l,r)…
求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ----------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm>   using namespace std;…
二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) --------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<cctype>   using namespace std;   typedef long l…
题目链接 环可以拆成链:对字符串排序能想到后缀数组. 完了.输出时忽略长度不足n的串,输出s[sa[i]+n-1],即排名为i的字符串的末尾. //4140kb 744ms #include <cstdio> #include <cstring> #include <algorithm> const int N=2e5+5; int n,tm[N],sa[N],rk[N],sa2[N]; char s[N]; void Get_SA() { int m=130,*x=r…
题目大意 给定\(k\)和长度\(\le10^5\)的串S 把串分成不超过\(k\)个子串,然后对于每个子串\(s\),他会从\(s\)的所有子串中选择字典序最大的那一个,并在选出来的\(k\)个子串中再选择字典序最大的那一个.他称其为"魔力串". 输出最小的魔力串 分析 最大值最小\(\Rightarrow\)二分+判定性问题 考虑对于选出来的\(k\)个子串\(s\),\(s\)中最大子串一定是\(s\)的某个后缀 做法 我们在所有本质不同字符串中按找字典序进行二分 得到一段字符…
Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i)…
题面 Description 话说练习后缀数组时,小C 刷遍 poj 后缀数组题, 各类字符串题闻之丧胆.就在准备对敌方武将发出连环杀时,对方一记无中生有,又一招顺 手牵羊,小C 程序中的原字符数组就被牵走了.幸运的是,小C 早已经求出了 SA[],为了 能东山再起,迅速 A 掉此题,他希望各位忠臣们能帮忙求出一组原字符数组的可行方案.已 知原字符数组由小写拉丁字母组成.且小C的SA[]也是有可能求错的, 原数组可能不存在. Input 输入文件只有一行且为用空格隔开的一个正整数 N. 接下来一…
题目链接 \(Description\) 给定SA数组,求满足SA[]的一个原字符串(每个字符为小写字母),无解输出-1. \(Solution\) 假设我们现在有suf(SA[j]),要构造suf(SA[i]) (要满足i>j) 考虑后缀的比较方式,先比较第一位,再比较suf(SA[i]+1)与suf(SA[j]+1) 若suf(SA[i]+1)>suf(SA[j]+1),则两字符串第一位可以相同:否则一定要在第一位满足suf(SA[i])>suf(SA[j]) 按照这种方式构造,就能…
Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色. 为了制作这个项链,小 H 购买了两个机器.第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠.例如:aba和aca连接起来,可以生成串abaaca或 abaca. 现在给出目标项链的样式,询问你需要使用第二个机器多少次才…
题目 求两数组归并后的数组最小字典序排列. 嘛,可能本人在贪心这块还是太弱了(或者说什么都弱),如果不知道是字符串题估计也想不起来用sa. 显然看得出归并时字典序小的那个数组先往里面加,这就是要比较两数组后缀的rank,方法就把两串相拼做后缀排序后比较. 这里附下贪心正确性证明,反正我不太会,只是感性认识一下. Upd:突然想起来这题其实可以hash+二分比较,码量稍小,不想写了 #include<bits/stdc++.h> using namespace std; typedef long…
题目链接 题目描述 对于一个给定的字符串,可以从左右两端取字符,依次排列构成一个新的字符串. 求可能构成的字符串中字典序 最小的一个. 例:ACDBCB -> ABCBCD 思路 参考自 xueyifan1993. 正确的 贪心 姿势: 记左端位置为 \(l\),右端位置为 \(r\),比较 \(suffix(l)\) 与 \(inv(prefix(r))\),取小者. 比较 则显然是借助 \(rank\) 数组. // 以及正确的I/O姿势真的重要... // scanf+printf:117…
根据height数组的定义,和当前后缀串i最长的相同串的长度就是max(height[i],height[i+1]),这个后缀贡献的最短不同串长度就是len=max(height[i],height[i+1]) 考虑这个贡献的范围,对于i~i+len,贡献是len,对于w=i+len+1~n可以更新w-len+1,也就是这长为len的串再向右延伸,可以证明这也是不重子串 这两个东西用两个线段树维护,w-len+1这个直接把-len+1打在线段树上,查询的时候再加回w即可 #include<ios…
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4556 本来只要查 ht[ ] 数组上的前驱和后继就行,但有长度的限制.可以二分答案解决!然后用主席树查区间内的 ht[ ] 的前驱和后继即可.(主席树弄对 rk 的权值线段树) 在主席树上走的复杂度应该不会比二分然后查看主席树的 log2 更差吧. #include<cstdio> #include<cstring> #include<algorithm> usi…
题目大意 在结尾动态插入字符,每次插入结束后输出当前串中本质不同的字串个数 题解 注意一开始是空串,然后我们我们可以打表观察规律 我们发现一直在开头插入字符和一直在结尾插入字符得到的答案是一样的 所以我们从开头插入字符 那么每次我们相于插入了一个后缀 这样就多了n-sa[i]个前缀 但是这些前缀中有重复的 所以我们要在已经插入的后缀中找出与之最长的lcp长度 减去这个长度就是我们得到的不同的字串个数了 由于求lcp时是对height一直取min 所以我们找最长的lcp是只需要找所有已经计算的了后…
很容易想到只考虑后缀长度必须为\(max(height[rk[i]],height[rk[i]+1])+1\)(即\([i,i+x-1]\)代表的串只出现过一次)然后我正着做一遍反着做一遍,再取一个\(min\)最后挂了... 设\(x=max(height[rk[i]],height[rk[i]+1])+1\)我们考虑\(i\)的贡献,会给区间\([i,i+x-1]\)一个贡献x ,设\(r=i+x-1\)然后会给r+1一个贡献x+1就是(r+1)-i+1,接着是r+2的贡献(r+2)-i+1…