【思维题、KMP】P3526 [POI2011]OKR-Periodicity 题解
P3526 [POI2011]OKR-Periodicity 题解
前言
一道非常厉害的思维题。看题解得到了一些提示搞出来了。
作为 2011 年的题还是很厉害的。
约定
- 定义 \(s[l,r]\) 为 \(s\) 当中下标为 \([l,r]\) 的字符组成的子串。
- \(st,ed\) 表示字符串的某段前缀和后缀。
- 一个串 \(t\) 是 \(s\) 的周期当且仅当 \(s=ttt\dots tt'\),其中 \(t'\) 是 \(t\) 的前缀。由此知道 \(s[i]=s[i+|t|]\)。
- \(p(p<|s|)\) 是串 \(s\) 的 \(\texttt{border}\) 当且仅当 \(s[1,p]=s[|s|-p+1,|s|]\)。 不难发现 \(|s|-p\) 是 \(s\) 的周期。
题目简述
- 给定由大写字母组成的字符串 \(s\),构造字典序最小的 \(\texttt{01}\) 串 \(t\) 使得 \(s,t\) 的所有周期长度组成集合相等。(下文称为 \(\texttt{01}\) 表示)
- 多测,\(T\leq 20,|s|\leq 2\times 10^5\)。
解题思路
两个显著的情况:
- 是如果 \(s\) 全部相等,那么肯定构造全 \(\texttt 0\) 串最优。
- 如果 \(s\) 没有周期,那么构造 \(\texttt{000}\dots\texttt{001}\) 肯定最优。
我们先看一个引理:
Weak Periodicity Lemma: 假设 \(s\) 有长度为 \(p,q\) 的周期,且 \(p+q\leq |s|\) 则 \(s\) 有长度为 \(\gcd(p,q)\) 的周期。
证明: 不妨设 \(p<q\)。考虑对于 \(i\leq q-p\),必然能找到 \(i'\equiv i(\bmod p)\)。必然有 \(i'+q\leq n,i'+q-p> i'\)。由【约定】,我们知道 \(s[i]=s[i']=s[i'+q]=s[i'+q-p]=s[i+q-p]\),也就是 \(q-p\) 是 \(s\) 的周期。辗转相除可证。
由引理得到推论:
推论:对于 \(s\) 的最小周期 \(r\),则对于所有的周期 \(R\leq |s|-r\) 只有 \(R\in\{r,2r,\dots, \left\lfloor\dfrac{|s|-r}{r}\right\rfloor\times r\}\)。
转到 \(\texttt{border}\) 上也就是所有 \(\geq r\) 的 \(\texttt{border}\) 只有 \(r+|s|\bmod r,2r+|s|\bmod r+\dots,|s|-r\)。
回到本题当中,分为两种情况:
\(s\) 的最小周期 \(\leq \dfrac{|s|}{2}\)
也就是 \(s\) 可以表示为 \(tt\dots tt'\) 的形式(\(t'\) 是 \(t\) 的前缀)。也可以说 \(s\) 可以表示为 \(t'ttt\dots t\) 的形式(\(t'\) 是 \(t\) 的后缀)。我们先递归求出 \(t't\) 的最小 \(\texttt{01}\) 表示 \(p’p\)。我们下面说明 \(s\) 的最小 \(\texttt{01}\) 表示是 \(p'ppp\dots p\)。首先 \(s\) 的 \(\texttt{border}\) 肯定是 \(t\) 的 \(\texttt{border}\)。所以前 \(|t't|\) 的最小 \(\texttt{01}\) 表示为 \(p'p\)。
观察 \(s\) 的形式如下:

我们已经得到 \(a\) 被 \(t'\) 表示,\(ba\) 被 \(t\) 表示。考虑框起来的一个 \(\texttt{border}\),可以得到后面的所有 \(ba\) 都会被 \(t\) 表示,证明完毕。合法性显然。
\(s\) 的最小周期 \(>\dfrac{|s|}{2}\)
那么不难发现 \(s\) 可以被表示为 \(tat\) 的形式。其中 \(t\) 是 \(s\) 的最大 \(\texttt{border}\)。我们先求出 \(t\) 的最小表示 \(p\),下面讨论 \(a\) 可以被替换为 \(\texttt{00}\dots\texttt 0,\texttt{00}\dots\texttt{01}\) 之一。
若 \(a\) 被替换为 \(\texttt{00}\dots\texttt 0\)。如果此时不合法,也就是有大于 \(|t|\) 的 \(\texttt{border}\) 出现,我们下面分类讨论。
- 情况 \(1\):\(\texttt{border}\) 如下图所示:

这是会发现 \(p\texttt{0}\dots\texttt0=\texttt{0}\dots\texttt0p\),得到 \(p\) 是全 \(\texttt 0\) 串。
- 情况 \(2\):\(\texttt{border}\) 对应情况如下图所示:

这个时候也不难得出 \(p\) 是全 \(\texttt0\) 串。
- 情况 \(3\):\(\texttt{border}\) 对应关系如下图所示:

我们什么也得不到。但是不难得到全 \(\texttt 0\) 串也满足情况 \(3\),所以只有情况 \(3\) 不满足。当时当我们把 \(a\) 表示换为 \(\texttt 0\dots\texttt {01}\) 的时候,\(a\) 在 \(\texttt{border}\) 当中的位置肯定和上面的位置一样,这时候就不满足了。证毕。
至此我们讨论完了所有 \(s\) 的情况,可以递归解决。
具体实现
我们梳理一下我们的递归函数 dfs(p) 需要干什么。
他的目的应当是寻找 \(s[1,p]\) 的最小表示。上面讨论了 \(4\) 种情况:
- \(s[1,p]\) 全部字符相等。把答案对应位全填 \(\texttt 0\)。
- \(s[1,p]\) 没有 \(\texttt{border}\)。除了最后一位填 \(\texttt 1\) 其他填 \(\texttt 0\)。
- \(s[1,p]\) 最小周期 \(len\) 满足 \(2len\leq p\),递归求出 \(p\bmod len+len\) 的表示,重复到后面得到答案。
- 否则最大 \(\texttt{border}\) 为 \(len\),递归求 \(len\) 的表示。尝试把答案 \(len+1,p-len\) 填入全 \(\texttt 0\) 查询是否合法,不合法把最后一位改为 \(\texttt 1\)。
给一份 dfs 及其他函数的参考代码:
const int MAXN=2e5+5;
char s[MAXN];int border[MAXN],fail[MAXN];
char ans[MAXN];
void KMP(int n,char *t,int *p){
p[1]=0;
for(int i=2;i<=n;i++){
p[i]=p[i-1];
while(p[i]&&t[p[i]+1]!=t[i]) p[i]=p[p[i]];
if(t[p[i]+1]==t[i]) p[i]++;
}
}
void dfs(int p){
bool sm=1;
for(int i=1;i<=p;i++) if(s[i]!=s[1]) sm=0;
if(sm){for(int i=1;i<=p;i++) ans[i]='0';return;}
if(border[p]==0){for(int i=1;i<=p-1;i++) ans[i]='0';ans[p]='1';return;}
int len=p-border[p];// 周期长度
if(len*2<=p){
dfs(len+p%len);
for(int i=len+p%len+1;i<=p;i++)
ans[i]=ans[i-len];
return;
}
len=border[p];
dfs(len);
for(int i=len+1;i<=p-len;i++) ans[i]='0';
for(int i=1;i<=len;i++)
ans[p-len+i]=ans[i];
KMP(p,ans,fail);
if(fail[p]!=len) ans[p-len]='1';
return;
}
void solve(){
cin>>(s+1);int n=strlen(s+1);
KMP(n,s,border);
dfs(n);
for(int i=1;i<=n;i++) putchar(ans[i]);
puts("");
}
【思维题、KMP】P3526 [POI2011]OKR-Periodicity 题解的更多相关文章
- 【思维题 kmp 构造】bzoj4974: [Lydsy1708月赛]字符串大师
字符串思博题这一块还是有点薄弱啊. Description 一个串T是S的循环节,当且仅当存在正整数k,使得S是T^k(即T重复k次)的前缀,比如abcd是abcdabcdab的循环节 .给定一个长度 ...
- 7月15日考试 题解(链表+状压DP+思维题)
前言:蒟蒻太弱了,全打的暴力QAQ. --------------------- T1 小Z的求和 题目大意:求$\sum\limits_{i=1}^n \sum\limits_{j=i}^n kth ...
- ZOJ 3829 贪心 思维题
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3829 现场做这道题的时候,感觉是思维题.自己智商不够.不敢搞,想着队友智商 ...
- C. Nice Garland Codeforces Round #535 (Div. 3) 思维题
C. Nice Garland time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- PJ考试可能会用到的数学思维题选讲-自学教程-自学笔记
PJ考试可能会用到的数学思维题选讲 by Pleiades_Antares 是学弟学妹的讲义--然后一部分题目是我弄的一部分来源于洛谷用户@ 普及组的一些数学思维题,所以可能有点菜咯别怪我 OI中的数 ...
- UVALive.3708 Graveyard (思维题)
UVALive.3708 Graveyard (思维题) 题意分析 这标题真悲伤,墓地. 在周长为1e4的圆周上等距分布着n个雕塑,现在要加入进来m个雕塑,最终还要使得这n+m个雕塑等距,那么原来的n ...
- codeforces ~ 1009 B Minimum Ternary String(超级恶心的思维题
http://codeforces.com/problemset/problem/1009/B B. Minimum Ternary String time limit per test 1 seco ...
- 计蒜客 28319.Interesting Integers-类似斐波那契数列-递推思维题 (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 I)
I. Interesting Integers 传送门 应该是叫思维题吧,反正敲一下脑壳才知道自己哪里写错了.要敢于暴力. 这个题的题意就是给你一个数,让你逆推出递推的最开始的两个数(假设一开始的两个 ...
- little w and Soda(思维题)
链接:https://ac.nowcoder.com/acm/contest/297/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- BZOJ 2734 洛谷 3226 [HNOI2012]集合选数【状压DP】【思维题】
[题解] 思维题,看了别人的博客才会写. 写出这样的矩阵: 1,3,9,... 2,6,18,... 4,12.36,... 8,24,72,... 我们要做的就是从矩阵中选出一些数字,但是不能选相邻 ...
随机推荐
- 微信小程序-组件生命周期方法
官方文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html 正如官方显示组件的生命周期中常用的 ...
- 【二】MADDPG多智能体算法实现(parl)【追逐游戏复现】
相关文章: [一]MADDPG-单智能体|多智能体总结(理论.算法) [二]MADDPG多智能体深度强化学习算法算法实现(parl)--[追逐游戏复现] 程序链接:直接fork:MADDPG多智能体深 ...
- PCIe诞生20年来最大变革!引入光学传输
PCI-SIG组织官方宣布,已经成立新的光学工作组(Optical Workgroup),研究为PCIe规范引入光学传输接口的可能性. PCIe标准是Intel 2001年提出的,2003年发布1.0 ...
- 手撕Udp套接字|实现群聊通信|实现Windows & Linux通信交互
专栏和Git地址 操作系统https://blog.csdn.net/yu_cblog/category_12165502.html?spm=1001.2014.3001.5482UdpSocke ...
- ASP.NET Core分布式项目实战(oauth2与open id connect 对比)--学习笔记
任务14:oauth2与open id connect 对比 以微博开放平台为例(微博登录接入--授权机制): https://open.weibo.com/wiki/授权机制 可以看到微博登录接入使 ...
- NC19999 [HAOI2016]放棋子
题目链接 题目 题目描述 给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行 ...
- java 从零开始手写 RPC (06) reflect 反射实现通用调用之客户端
通用调用 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 java 从零开始手写 RPC (03) 如何 ...
- 【Unity3D】UGUI之Button
1 Button属性面板 在 Hierarchy 窗口右键,选择 UI 列表里的 Button 控件,即可创建 Button 控件,选中创建的 Button 控件,按键盘[T]键,可以调整 But ...
- springboot jpa自定义SQL查询
说明 在使用JPA实现数据持久化过程中经常会遇到这种情况:我有2张表是一对多的关系,需要通过一个外键ID去关联查询到另外一张表的字段.例如,1张商品表food_info其中存有商品分类ID categ ...
- 解决:Not found the kernel library or the kernel library is invalid
问题说明: 今天运行一个E语言写的程序报错, 看样子是缺少核心依赖库. 解决方法 去下载个易语言安装包安装一下即可.比如我安装的是: 易语言5.6完美破解版(精简版).exe 下载地址:https:/ ...