题目背景

生牛哥终于打通了“字符消除”,可是他又被它的续集难倒了。


题目传送门(内部题52)


输入格式

第一行$n$表示数据组书。
接下来每行一个字符串。(只包含大写字母)


输出格式

每组数据输出一个$01$串。


样例

样例输入:

3
YDYYDY
JRYJREJRYJR
YDYAKYDY

样例输出:

010010
01001101001
01000010


数据范围与提示


题解

为方便,我们设串长为$S$。

首先,来解释一下什么是可行$t$。

对于样例中的第一个串$"YDYYDY"$,我看它比较帅,所以就拿它举例。

它的可行$t$集合为$3$和$6$,为什么呢?

对于一个长度为$3$的环,我们可以这么填:

这时,我们填成了一圈,然后我们去填第二圈:

刚好填完,所以它是一个可行$t$,长度为$6$时同理,可是当长度为$4$当我们填到第五个$D$时发现那个位置已经填了$Y$,所以就不可行了。

题意解释完了,我们现在开始考虑这道题应该怎么办?

先来考虑如何求出可行$t$的集合。

我们发现,如果这个串有一个长度为$len$的公共前后缀,那么其中一个可行$t$就是$len-1$,来解释一下:

对于一个公共前后缀,如下图:

橙色区域是公共前后缀,绿色区域是串,显然$a\sim b$点即为长度$len$,那么当我们处理到$c$点时完成了一个环,但是接下来我们要填的$c\sim d$这部分和$a\sim b$是一样的,所以这个$n-len$就是一个长度$t$。

对于$t$的集合,我们可以通过$hash$或者是$KMP$在$\Theta(S)$的时间复杂度内求出。

虽说我用的是$hash$,但是我想讲一下$KMP$如何求出,我们只需要从$n$向前不断的找$next$就好了,也就是$next[next[i]]$,下面来解释为什么:

设橙色区域即$a\sim d$是$next[n]$,也就是说$1-$橙色区域是一组可行$t$,现在另紫色区域即$a\sim b$是$next[next[n]]$,现在来证明$1-$紫色区域是一组可行$t$:

  因为$a\sim d$和$e\sim h$相同,$a\sim b$、$c\sim d$、$e\sim f$、$g\sim h$相同,所以我们可以当填一圈填到$g$时接着填完最后$g\sim h$($a\sim b=g\sim h$)。

现在再来考虑如何生成$01$串,显然枚举是不可能的。

设$a$数组表示所有的公共前后缀集合(其实就是$KMP$中的$next$数组),注意不是可行$t$,那么这时候分两种情况:

  $\alpha.a[k]\times 2\geqslant a[k+1]$:这时候我们就将$01$串后面接上一段长度为$a[k+1]-a[k]$的后缀即可,如下图:

  

  我们现在已经处理好了$a\sim c$这一段,现在要将填$c\sim d$这一段,不妨另$len(b\sim c)=len(c\sim d)$注意现在$c$是$next[d]$,也就是说我们要使$a\sim c=b\sim d$,那么显然是要将$b\sim c$复制到$c\sim d$。

  $\beta.a[k]\times 2<a[k+1]$:考虑$next$数组的含义,为了保证解最优,我们一定是先将整个串复制一遍放在最后,然后在中间先填满$0$,如果不行的话将最后一个$0$换成$1$即可,至于如何判断,暴力搞就好了,因为如果$0$不行的话最后以为是$1$肯定行。

这样我们就完美的解决了这道题。

时间复杂度:$\Theta(\sum S)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n;
char ch[200001];
int b[200001],que[200001],nxt[200001],p;
unsigned long long a[200001],mod[200001];
void pre_work()
{
memset(nxt,0,sizeof(nxt));
memset(b,0,sizeof(b));
p=que[0]=0;
}
void KMP(int l,int r)
{
for(int i=l+1;i<=r;i++)
{
while(p&&b[i]!=b[p+1])p=nxt[p];
if(b[i]==b[p+1])p++;
nxt[i]=p;
}
}
int main()
{
int T;scanf("%d",&T);
mod[1]=1;
for(int i=2;i<=200000;i++)mod[i]=mod[i-1]*131;
while(T--)
{
scanf("%s",ch+1);
pre_work();
n=strlen(ch+1);
a[1]=ch[1]-'A'+1;
for(int i=2;i<=n;i++)
a[i]=a[i-1]*131+ch[i]-'A'+1;
for(int i=0;i<=n;i++)
if(a[i+1]==a[n]-a[n-i-1]*mod[i+2])que[++que[0]]=i+1;
if(que[1]>1)b[que[1]]=1;
KMP(1,que[1]);
for(int i=2;i<=que[0];i++)
{
if(que[i]<=que[i-1]<<1)
{
for(int j=que[i-1]+1;j<=que[i];j++)
b[j]=b[j+que[i-1]-que[i]];
KMP(que[i-1],que[i]);
}
else
{
KMP(que[i-1],que[i]-que[i-1]-1);
int now=p,zero=1,len=que[i]-que[i-1];
while(now)
{
if(!b[now+1]&&!(len%(len-now-1))){b[len]=1;break;}
now=nxt[now];
}
if(!b[now+1]&&!(len%(len-now-1)))b[len]=1;
KMP(len-1,len);
nxt[len]=p;
len=que[i]-que[i-1];
for(int j=1;j<=que[i-1];j++)b[len+j]=b[j];
KMP(len,len+que[i-1]);
}
}
for(int i=1;i<=n;i++)printf("%d",b[i]);
puts("");
}
return 0;
}

rp++

[CSP-S模拟测试]:字符消除2(hash+KMP)的更多相关文章

  1. [CSP-S模拟测试]:字符交换(贪心+模拟)

    题目传送门(内部题136) 输入格式 输入文件第一行为两个正整数$n,k$,第二行为一个长度为$n$的小写字母字符串$s$. 输出格式 输出一个整数,为对字符串$s$进行至多$k$次交换相邻字符的操作 ...

  2. [CSP-S模拟测试]:回文(hash+二维前缀和)

    题目描述 闲着无聊的$YGH$秒掉上面两道题之后,开始思考有趣的回文串问题了. 他面前就有一个漂浮着的字符串.显然$YGH$是会$manacher$的,于是他随手求出了这个字符串的回文子串个数.但是他 ...

  3. [CSP-S模拟测试]:字符(模拟+剪枝)

    题目传送门(内部题33) 输入格式 第一行,两个整数$T,C$,表示测试数据组数和字符种类数.对于每组数据:第一行,一个正整数$M$:接下来的$M$行,每行两个整数$P_k,X_k$($S$的下标从$ ...

  4. Android单元测试与模拟测试详解

    测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabri ...

  5. csp-s模拟测试94

    csp-s模拟测试94 一场简单题,打爆了.$T1$脑抽分解质因数准备分子分母消,想了半天发现$jb$互质直接上天,果断码了高精滚蛋.$T2$无脑手玩大样例,突然灵光一闪想到映射到前$K$大小的区间, ...

  6. csp-s模拟测试85

    csp-s模拟测试85 $T1$全场秒切没有什么区分度,$T2$全场成功转化题意但是我并不会打,$T3$暴力都没打很遗憾. 100 00:21:49 02:56:35 02:56:49 135 02: ...

  7. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  8. Fiddler: AutoResponder 构建模拟测试场景

    AutoResponder 可用于拦截某一请求,并重定向到本地的资源,或者使用Fiddler的内置响应.可用于调试服务器端代码而无需修改服务器端的代码和配置,因为拦截和重定向后,实际上访问的是本地的文 ...

  9. NOIP模拟测试17&18

    NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...

随机推荐

  1. MySQL 查询语句--------------进阶5:分组查询

    #进阶5:分组查询 /* select 分组函数,列(要求出现在group by的后面) from 表 [where 筛选条件] group by 分组的列表 [order by 子句] 注意: 查询 ...

  2. 《JAVA设计模式》之外观模式(Facade)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述门面(Facade)模式的: 门面模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的门面对象进行.门面模式提供一个高层次的接口 ...

  3. POJ-1611.TheSuspects.(并查集)

    The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 55832   Accepted: 26501 De ...

  4. 断路器,AOP实现断路器模式 ------------Hystrix

    断路器:https://martinfowler.com/bliki/CircutiBreaker.html 核心思想: 在断路器对象中封装受保护的方法调用. 该断路器监控调用和断路情况 调用失败触发 ...

  5. python 分析 知乎粉丝数据

    昨天花了一下午写了一个小爬虫,用来分析自己的粉丝数据.这个真好玩!今天帮了群里好多大V也爬了他们的数据.运行速度:每分钟5千粉丝以上.暂时先写成这样,这两天要准备补考,没有时间继续玩这个. 下次要改进 ...

  6. Day7-----Python的序列类(有子类:元组类,列表类)

    序列类型 1.基本介绍: 序列类型是一种基类类型  ,既然被称为那就肯定是有道理的,关于序列 它有  正向  和  反向  两种序号,正向序号从零开始,反向序号从负一开始 a = '例如这个字符串' ...

  7. C. Trailing Loves (or L'oeufs?) (质因数分解)

    C. Trailing Loves (or L'oeufs?) 题目传送门 题意: 求n!在b进制下末尾有多少个0? 思路: 类比与5!在10进制下末尾0的个数是看2和5的个数,那么 原题就是看b进行 ...

  8. 如何优化MySQL千万级大表

    很好的一篇博客,转载 如何优化MySQL千万级大表 原文链接::https://blog.csdn.net/yangjianrong1985/article/details/102675334 千万级 ...

  9. BUUCTF--不一样的flag

    测试文件:https://buuoj.cn/files/91b89e765c9aff8e82690c0868975b37/0bf39b5d-5f2f-4095-a921-fb5c20f53f21.zi ...

  10. JavaScript 中的 Function.prototype.bind() 方法

    转载自:https://www.cnblogs.com/zztt/p/4122352.html Function.prototype.bind()方法 bind() 方法的主要作用就是将函数绑定至某个 ...