题意

给定字符串 \(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) << endl using 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_shadow
freopen ("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; }

LOJ #3103. 「JSOI2019」节日庆典的更多相关文章

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

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

  2. Loj #3102. 「JSOI2019」神经网络

    Loj #3102. 「JSOI2019」神经网络 题目背景 火星探险队发现,火星人的思维方式与人类非常不同,是因为他们拥有与人类很不一样的神经网络结构.为了更好地理解火星人的行为模式,JYY 对小镇 ...

  3. 【LOJ】#3102. 「JSOI2019」神经网络

    LOJ#3102. 「JSOI2019」神经网络 首先我们容易发现就是把树拆成若干条链,然后要求这些链排在一个环上,同一棵树的链不相邻 把树拆成链可以用一个简单(但是需要复杂的分类讨论)的树背包实现 ...

  4. 【LOJ】#3101. 「JSOI2019」精准预测

    LOJ#3101. 「JSOI2019」精准预测 设0是生,1是死,按2-sat连边那么第一种情况是\((t,x,1) \rightarrow (t + 1,y,1)\),\((t + 1,y, 0) ...

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

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

  6. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  7. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  8. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  9. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

随机推荐

  1. Android编程权威指南笔记

    学习android开发,你需要对java语言,包括类,对象,接口,监听器,包,内部类,匿名内部类有所了解. android studio 的下载与安装 可以从android开发者网站下载android ...

  2. SpringMVC相关试题

    1.下列相关Spring自动装配的说法中,错误的是( ). (选择一项) A:在Spring配置文件中,可以通过<bean>元素的autowire属性指定自动装配方式B: autowire ...

  3. 记一次vue+vuex+vue-router+axios+elementUI开发(三)

    项目用到了状态管理工具 Vuex  中文文档:https://vuex.vuejs.org/zh/guide/ 大家都知道,vue中可用props将父组件的数据传递给子组件,但是有个问题,子组件一般不 ...

  4. poi导入读取时间格式问题

    万能处理方案: 所有日期格式都可以通过getDataFormat()值来判断 yyyy-MM-dd-----14 yyyy年m月d日--- 31 yyyy年m月-------57 m月d日  ---- ...

  5. 【Alpha】“北航社团帮”小程序v1.0发布声明

    我们的"北航社团帮"小程序发布啦!!! Alpha版本功能 功能列表和详情图 模块 功能 登录 授权登录,游客模式,无需填写信息 活动展示 首页轮播热度最高的四个活动,查看活动详情 ...

  6. eggjs的参数校验模块egg-validate的使用和进一步定制化升级

    简单讲一下这个egg-validate egg-validate是基于parameter的. 安装 npm install --save egg-validate 启用 // config/plugi ...

  7. 【深入学习linux】Linux命令格式

    一.命令基本格式 命令提示符 [root@localhost ~]# root 代表当前登录用户,Linux当中管理员账号是 root localhost 代表主机名 ~ 代表当前所在目录(家目录), ...

  8. Linux创建用户,SFTP只允许访问指定目录

    首先创建用户 useradd lus1passwd lus1 我这里配置lus1这个用户目录,为sftp指向目录,即/home/lus1/ vim /etc/ssh/sshd_config //这个记 ...

  9. 阻止Bootstrap 模态框点击背景空白处自动关闭

    问题描述 模态框点击空白处,会自动关闭,怎么阻止关闭事件呢? 解决方法 在HTML页面中编写模态框时,在div初始化时添加属性 aria-hidden=”true” data-backdrop=”st ...

  10. css---移动端网站专属BUG【苹果手机】

    最近在前端写页面的时候,遇到了三个苹果手机的专属BUG,记录下... BUG1:苹果手机 form 表单的input有阴影 解决方法: input { /* 1 */ overflow: visibl ...