\(\mathcal{Description}\)

  求出处 owo。

  给定一个长度为 \(n\),仅包含小写字母的字符串 \(s\),问是否存在长度为 \(n\),仅包含小写字母的字符串 \(t\),使得 \(t<s\) 且 \(s,t\) 的后缀数组(\(\text{Suffix Array}\),sa[])相同。

  \(n\le50\)。(建议开到 \(n\le2\times10^5\)。

\(\mathcal{Solution}\)

奇怪的结论

  若存在 \(t\),则存在一个 \(t\),其与 \(s\) 仅相差一个字符。考试的时候我猜出来了 w!

算法

  有了上面的结论就非常简单了。首先一个显而易见的特判:若 \(s\) 的字符集不是小写字母的一段前缀,显然存在 \(t\)。

  然后,先求出原串的 sa[]。尝试让某个 \(s_i\) 减小 \(1\)。显然,修改 \(s_i\) 不影响 sa[],需要保证 \(\operatorname{suffix(i)}\) 是以 \(s_i\) 开头的后缀中最小的。则满足条件的 \(s_i\) 仅有字符集大小个。暴力修改这些 \(s_i\),求出 sa2[] 与原来的 sa[] 比较即可。

  复杂度 \(\mathcal O(|\mathit{\Sigma}|n\log n)\)。标算是暴力 sortsa[],且尝试修改了所有的 \(s_i\),复杂度 \(\mathcal O(n^3\log n)\),并不优秀。

\(\mathcal{Code}\)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream> #define YES() ( puts ( "Exists" ), exit ( 0 ) )
#define NO() ( puts ( "Does not exist" ), exit ( 0 ) ) const int MAXN = 50;
int n, sa[MAXN + 5];
char s[MAXN + 5]; inline void suffixSort ( int* sa ) {
int m = 'z', x[200] {}, y[200] {}, c[200] {};
for ( int i = 1; i <= n; ++ i ) c[i] = 0;
for ( int i = 1; i <= n; ++ i ) ++ c[x[i] = s[i]];
for ( int i = 1; i <= m; ++ i ) c[i] += c[i - 1];
for ( int i = n; i; -- i ) sa[c[x[i]] --] = i;
for ( int j = 1; j <= n; j <<= 1 ) {
int cnt = 0;
for ( int i = n - j + 1; i <= n; ++ i ) y[++ cnt] = i;
for ( int i = 1; i <= n; ++ i ) if ( sa[i] > j ) y[++ cnt] = sa[i] - j;
for ( int i = 1; i <= m; ++ i ) c[i] = 0;
for ( int i = 1; i <= n; ++ i ) ++ c[x[i]];
for ( int i = 1; i <= m; ++ i ) c[i] += c[i - 1];
for ( int i = n; i; -- i ) sa[c[x[y[i]]] --] = y[i], y[i] = 0;
std::swap ( x, y ), x[sa[1]] = 1, cnt = 1;
for ( int i = 2; i <= n; ++ i ) {
x[sa[i]] = cnt += y[sa[i]] ^ y[sa[i - 1]] || y[sa[i] + j] ^ y[sa[i - 1] + j];
}
if ( ( m = cnt ) == n ) break;
}
} inline void precheck () {
bool used[26] {};
for ( int i = 1; i <= n; ++ i ) used[s[i] - 'a'] = true;
for ( int i = 0, ue = false; i < 26; ++ i ) {
if ( ue && used[i] ) YES ();
ue |= ! used[i];
}
} inline void check () {
int nsa[MAXN + 5] {};
suffixSort ( nsa );
for ( int i = 1; i <= n; ++ i ) if ( nsa[i] ^ sa[i] ) return ;
YES ();
} int main () {
freopen ( "sa.in", "r", stdin );
freopen ( "sa.out", "w", stdout );
scanf ( "%s", s + 1 ), n = strlen ( s + 1 );
precheck (), suffixSort ( sa );
for ( int i = 1, las = 'a', t; i <= n; ++ i ) {
if ( s[sa[i]] == las ) continue;
t = s[sa[i]], s[sa[i]] = las, check (), las = s[sa[i]] = t;
}
return NO (), 0;
}
```cpp

Solution -「SV 2020 Round I」SA的更多相关文章

  1. Solution -「SV 2020 Round I」「SRM 551 DIV1」「TC 12141」SweetFruits

    \(\mathcal{Description}\)   link.   给定 \(n\) 个水果,每个结点可能有甜度 \(v_i\),或不甜(\(v_i=-1\)).现在把这些水果串成一棵无根树.称一 ...

  2. Solution -「USACO 2020.12 P」Spaceship

    \(\mathcal{Description}\)   Link.   Bessie 在一张含 \(n\) 个结点的有向图上遍历,站在某个结点上时,她必须按下自己手中 \(m\) 个按钮中处于激活状态 ...

  3. Solution -「USACO 2020.12 P」Sleeping Cows

    \(\mathcal{Description}\)   Link.   有 \(n\) 个牛棚,大小为 \(t_{1..n}\),\(n\) 头奶牛,大小为 \(s_{1..n}\),奶牛只能住进不小 ...

  4. 「LibreOJ NOI Round #2」不等关系

    「LibreOJ NOI Round #2」不等关系 解题思路 令 \(F(k)\) 为恰好有 \(k\) 个大于号不满足的答案,\(G(k)\) 表示钦点了 \(k\) 个大于号不满足,剩下随便填的 ...

  5. LibreOJ #507. 「LibreOJ NOI Round #1」接竹竿

    二次联通门 : LibreOJ #507. 「LibreOJ NOI Round #1」接竹竿 /* LibreOJ #507. 「LibreOJ NOI Round #1」接竹竿 dp 记录一下前驱 ...

  6. Solution -「ZJOI 2020」「洛谷 P6631」序列

    \(\mathcal{Description}\)   Link.   给定一个长为 \(n\) 的非负整数序列 \(\lang a_n\rang\),你可以进行如下操作: 取 \([l,r]\),将 ...

  7. Solution -「JOISC 2020」「UOJ #509」迷路的猫

    \(\mathcal{Decription}\)   Link.   这是一道通信题.   给定一个 \(n\) 个点 \(m\) 条边的连通无向图与两个限制 \(A,B\).   程序 Anthon ...

  8. Solution -「NOI 2020」「洛谷 P6776」超现实树

    \(\mathcal{Description}\)   Link.   对于非空二叉树 \(T\),定义 \(\operatorname{grow}(T)\) 为所有能通过若干次"替换 \( ...

  9. Solution -「FJWC 2020」人生

    \(\mathcal{Description}\)   OurOJ.   有 \(n\) 个结点,一些结点有染有黑色或白色,其余待染色.将 \(n\) 个结点染上颜色并连接有向边,求有多少个不同(结点 ...

随机推荐

  1. 05.python解析式与生成器表达式

    解析式和生成器表达式 列表解析式 列表解析式List Comprehension,也叫列表推导式 #生成一个列表,元素0-9,将每个元素加1后的平方值组成新的列表 x = [] for i in ra ...

  2. CTF-sql-order by盲注

    本文章只讨论了order by盲注,关于order by的报错等注入不在本文章讨论范围,另有文章. 让我们先来看看本文章所使用的表的内容,如下图: 接下来先了解一下order by的基础知识: ord ...

  3. RHCSA 第二天

    1.Linux中的文件类型以及符号的表示 (1) 普通文件: 使用 ls -l 命令后,第一列第一个字符为 "-" 的文件为普通文件,如上图所示,普通文件一般为灰色字体,绿色字体的 ...

  4. 《剑指offer》面试题48. 最长不含重复字符的子字符串

    问题描述 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度.   示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串 ...

  5. 小程序onShareAppMessage有点迷

    小程序遇到的问题 起因 目前项目需求是分享时携带参数去进行裂变,但是在查看微信文档后发现有onShareAppMessage这个页面处理事件可以使用.事件可以使用return一个Object,用于自定 ...

  6. [CISCN2019 华东南赛区]Web11

    [CISCN2019 华东南赛区]Web11 写在前面 参考文章:Smarty SSTI 1.{php}{/php} Smarty已经废弃{php}标签,强烈建议不要使用.在Smarty 3.1,{p ...

  7. Xbatis:SpringBoot 数据管理框架

    目录 安装 下载源码 编译源码 添加依赖 数据表 数据源 Xbatis XbatisManager Database/Table/Column Column Table Database Create ...

  8. 浅谈MySQL同步到ElasticSearch的几种方式及其优缺点

    同步双写 优点:业务逻辑简单. 缺点: 硬编码,有需要写入mysql的地方都需要添加写入ES的代码: 业务强耦合: 存在双写失败丢数据风险: 性能较差:本来mysql的性能不是很高,再加一个ES,系统 ...

  9. 学习AJAX必知必会(1)~Ajax

    一.ajax(Asynchronous JavaScript And XML,即异步的 JS 和 XML) 1.通过 AJAX 可以在浏览器中向服务器发送异步请求实现无刷新获取数据. 2.优势:无刷新 ...

  10. ipython notebook教程

    一.简介 Jupyter Notebook是一个开源的Web应用程序,允许用户创建和共享包含代码.方程式.可视化和文本的文档.它的用途包括:数据清理和转换.数值模拟.统计建模.数据可视化.机器学习等等 ...