题意

给定字符串 \(S\) ,对于 \(S\) 的每个前缀 \(T\) 求 \(T\) 所有循环同构串的字典序最小的串,输出其起始下标。(如有多个输出最靠前的)

\(|S| \le 3 \times 10^6\)

题解

本文参考了官方题解。

假设我们现在考虑前缀 \(S[1 \dots k]\) ,我们考虑哪些起始位置可能成为答案,我们称作候选点。也就是对于这些候选点来说,对于 \(i \ge k\) ,他们永远都会比非候选点更加优秀。

我们首先可以通过不循环移位比出他们的字典序的话,肯定可以直接看出哪个一定不是候选点。

性质一:假设两个位置 \(i < j\) 。 如果 \(\mathrm{lcp}(S[i \dots n],S[j \dots n]) \le k − j\) , 那么 \(i,j\) 之间肯定有一个不是候选点.

读者自证不难,利用上这个性质才是关键。

我们假设得到 \(S[1 \dots k - 1]\) 的候选点集 \(P\) ,对于 \(i, j \in P, i < j\) 那么一定有 \(\mathrm{lcp}(S[i \dots n], S[j \dots n]) > (k - 1) - j\) ,我们只需要找出是否存在一个 \(\mathrm{lcp}(S[i \dots n],S[j \dots n]) \le k − j\) 即可排除一个候选点。

我们显然只需要比较 \(S[i + k - j]\) 与 \(S[k]\) 就能比出来了,但是枚举所有点对是十分浪费的一件事。我们只考虑比较距离最远两个元素,留下较优的元素即可。

然后这样看起来还是 \(\mathcal O(n^2)\) 的,但似乎能跑前 \(50pts\) 。(也许有更严谨的更优复杂度吧)

然后还需要利用一个神奇的性质优化候选点数。

性质二:对于两个点 \(i < j\) , 假设 \(\mathrm{lcp}(S[i \dots n],S[j \dots n]]) > k − j\) , 如果有 \(k − j \ge j − i\) , 那么 \(j\) 不是候选点。

这个性质看上去没有那么显然了。

证明:这个性质是有最小循环表示的某个性质得来的, 假设串 \(S = S_1 S_1 S_2\) ,其中 \(S_1, S_2\) 是任意两个子串。

  • 要么有 \(S_1S_1S_2 \le S_1S_2 S_1 \le S_2S_1S_1\) 。
  • 要么有 \(S_1S_1S_2 \ge S_1S_2 S_1 \ge S_2S_1S_1\) 。

这个讨论 \(S_1, S_2\) 字典序大小不难发现。

那么如果有 \(k - j \ge j - i\) 那么 \(S[1 \dots k]\) 形如 \(ABBC\) ,那么我们把这两个后缀即可用 \(BBCA\) 和 \(BCAB\) 表示。把 \(S_1\) 设成 \(B\) ,\(S_2\) 设成 \(CA\) ,那么其实就是 \(S_1S_1S_2\) 与 \(S_1S_2S_1\) ,显然后者一定会被另外两个循环串包在中间,一定不如其他两个中的一个优。

利用上了这个性质,那么就有相邻两个候选点距离翻倍,那么只有 \(\mathcal O(\log n)\) 个候选点了。

这样的话,看似我们可以利用各种后缀数据结构在 \(\mathcal O(n \log n)\) 内轻松愉悦的解决。

实则不然。。。除非你用 \(\text{SA-IS}\) ,那当我没说。

我们预处理那里的复杂度要尽量降低,我们还需要知道一个性质。

性质三:对于任意两个候选点 \(i < j\) 那么 \(S[j \dots k]\) 是 \(S[i \dots k]\) 的一个前缀。

这个利用性质一不难发现。

那么我们发现我们每次其实只需要比较一个后缀和原串的字典序大小,这正好契合了 \(\mathrm{ExKmp}\) 的用途。

不会的话可以看我之前的学习笔记 qwq

然后预处理就变成 \(\mathcal O(n)\) ,总复杂度是 \(\mathcal O(n \log n)\) 。

总结

求区间最小(循环)后缀,都可以考虑候选点只有 \(\mathcal O(\log n)\) 个的神奇性质。

代码

#include <bits/stdc++.h>#define For(i, l, r) for (register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for (register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Rep(i, r) for (register int i = (0), i##end = (int)(r); i < i##end; ++i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endlusing namespace std;template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }inline int read() {int x(0), sgn(1); char ch(getchar());for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);return x * sgn;
}void File() {
#ifdef zjp_shadowfreopen ("3103.in", "r", stdin);freopen ("3103.out", "w", stdout);
#endif
}const int N = 3e6 + 1e3;void Get_Next(char *S, int *next) {int lenS = strlen(S + 1), p = 1, pos;next[1] = lenS;while (p + 1 <= lenS && S[p] == S[p + 1]) ++ p;next[pos = 2] = p - 1;For (i, 3, lenS) {int len = next[i - pos + 1];if (len + i < p + 1) next[i] = len;else {int j = max(p - i + 1, 0);while (i + j <= lenS && S[j + 1] == S[i + j]) ++ j;p = i + (next[pos = i] = j) - 1;}}
}char S[N]; int lcp[N], n; vector<int> cur;inline int cmp(int p, int len) {return lcp[p] >= len ? 0 : (S[lcp[p] + 1] < S[p + lcp[p]] ? 1 : -1);
}inline int cmp(int x, int y, int len) {static int res; assert(x > y);if ((res = cmp(y + (len - x + 1), x - y))) return res > 0 ? x : y;if ((res = cmp(x - y + 1, y - 1))) return res > 0 ? y : x;return y;
}int main () {File();scanf ("%s", S + 1); n = strlen(S + 1); Get_Next(S, lcp);For (k, 1, n) {vector<int> tmp(1, k);for (int i : cur) {while (!tmp.empty() && S[i + k - tmp.back()] < S[k]) tmp.pop_back();if (tmp.empty() || S[i + k - tmp.back()] == S[k]) {while (!tmp.empty() && k - tmp.back() >= tmp.back() - i) tmp.pop_back();tmp.push_back(i);}}cur = tmp; int ans = cur[0];For (i, 1, cur.size() - 1) ans = cmp(ans, cur[i], k);printf ("%d%c", ans, k == kend ? '\n' : ' ');}return 0;}

转载于:https://www.cnblogs.com/zjp-shadow/p/10809654.html

LOJ #3103. 「JSOI2019」节日庆典相关推荐

  1. 【LOJ】#3103. 「JSOI2019」节日庆典

    LOJ#3103. 「JSOI2019」节日庆典 能当最小位置的值一定是一个最小后缀,而有用的最小后缀不超过\(\log n\)个 为什么不超过\(\log n\)个,看了一下zsy的博客.. 假如\ ...

  2. 「JSOI2019」节日庆典 (Z-Algorithm)

    传送门 考虑一个后缀 Si...nS_{i...n}Si...n​,如果加上一个任意字符 ccc 可以使得 Si...ncS_{i...n}cSi...n​c 为字典序最小的后缀,那么将其称为好后缀, ...

  3. 【LOJ3103】「JSOI2019」节日庆典

    [题目链接] 点击打开链接 [思路要点] 考虑一种暴力维护候选点集的做法. 即,在字符串不断增长的同时,若已经可以确定 TiT_iTi​ 不再可能成为字典序最小的循环后缀,则将 iii 在候选点集中删 ...

  4. Loj #2568. 「APIO2016」烟花表演

    Loj #2568. 「APIO2016」烟花表演 题目描述 烟花表演是最引人注目的节日活动之一.在表演中,所有的烟花必须同时爆炸.为了确保安全,烟花被安置在远离开关的位置上,通过一些导火索与开关相连 ...

  5. Loj #3111. 「SDOI2019」染色

    Loj #3111. 「SDOI2019」染色 题目描述 给定 \(2 \times n\) 的格点图.其中一些结点有着已知的颜色,其余的结点还没有被染色.一个合法的染色方案不允许相邻结点有相同的染色 ...

  6. Loj #3055. 「HNOI2019」JOJO

    Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...

  7. LOJ#2230. 「BJOI2014」大融合

    LOJ#2230. 「BJOI2014」大融合 题目描述 小强要在$N$个孤立的星球上建立起一套通信系统.这套通信系统就是连接$N$个点的一个树.这个树的边是一条一条添加上去的. 在某个时刻,一条边的 ...

  8. loj#2143. 「SHOI2017」组合数问题

    loj#2143. 「SHOI2017」组合数问题 题目描述 Solution 考虑转化一下我们要求的东西. ∑i=0n(nkik+r)=∑i=0n(nki)[i≡r(modk)]\sum_{i=0} ...

  9. LOJ#2542. 「PKUWC2018」随机游走

    LOJ#2542. 「PKUWC2018」随机游走 题目描述 Solution 去过一个点集中所有节点的期望时间不好求,考虑min−maxmin-maxmin−max容斥,转化为求第一次到达某一个点集 ...

最新文章

  1. 直播技术(从服务端到客户端)二
  2. JavaScript正则表达式-基础入门
  3. 数据格式转换(一)PDF转换技术
  4. Hessian Binary Web Service Protocol远程接口调用入门
  5. Django博客--3.创作后台开启
  6. DAY3-“忙里偷闲”找你玩耍2018-1-11
  7. 雪城大学信息安全讲义 六、输入校验
  8. 转换运行时获取DTP语义组
  9. vue中配置不同的代理同时访问不同的后台
  10. vue 绑定 class 和 内联样式(style)
  11. 假疫苗事件,错在企业,责任在管理部门
  12. Spring AOP 讲解(Pointcut、Before、Around、AfterReturning、After)
  13. rgba通道转rgb,将RGBA颜色转换为RGB
  14. 关于BetterScroll 2.0版本出现BScroll is not defined 的解决方案
  15. 数据库范式(1 2 3 BCNF范式)详解
  16. 揭秘世界最大对撞机:将破解五大科学谜团(图)
  17. python bytes
  18. 用计算机弹奏的成都,抖音成都怎么用计算器弹奏_抖音成都计算器乐谱_管理资源吧...
  19. 网页版邮箱提取/采集软件
  20. 全网最全的qt连接mysql的应用,学生信息管理系统(展示全部代码)

热门文章

  1. z77主板可以用nv_出新也可以选旧 7款优质Z77主板推荐
  2. 如何利用 Selenium 对已打开的浏览器进行爬虫!
  3. 给2020年计算机考研学弟学妹的意见
  4. PHP Request请求封装
  5. 快速了解PROFINET通讯协议以及相关产品如何解决客户现场实际问题
  6. PCB BOM单制作规范
  7. Ubuntu18安装ROS melodic
  8. 适配器Adapter
  9. lamp一键安装操作
  10. 如何自学网络安全 才不会成为脚本小子?