[agc007f] Shik and Copying String 模拟神题
Description
“全”在十分愉快打工,第0天,给了他一个仅有小写字母构成的长度为N的字符串S0,在之后的第i天里,“全”的工作是将Si−1复制一份到一个新的字符串Si中,在接下来的描述中,我们用Si[j]表示串Si中的第j个字符
然而“全”十分不熟练,在复制的时候他容易出错。比如说在复制Si−1[j]到Si[j]的时候有时他会把Si[j]上的字符写成Si[j−1]Si[j−1],而不是本应被写上去的Si−1[j],更具体一点就是新串中的字符Si[j]可能等于Si[j−1]或者Si−1[j]
这让“全”很困扰,现在他给你S0和另一个长度同样为N的字符串T,希望你求出一个最小的i,能满足Si=T,如果不存在这样的i,输出−1
Input
第一行一个正整数N
第二行一个字符串S0
第三行一个字符串T
Output
输出最小的满足条件的i,无解输出−1
Sample Input
#Sample1
5
abcde
aaacc
#Sample2
5
abcde
abcde
#Sample3
4
acaa
aaca
#Sample4
5
abcde
bbbbb
Sample Output
#Sample1
2
#Sample2
0
#Sample3
2
#Sample4
-1
HINT
数据范围:
对于100%的数据,1<=N<=10^6,全部都是小写字母
样例解释:
Sample1:S0=abcde,S1=aaccc,S2=aaacc
Sol
神题。
我们首先可以预处理出来T中每一个字符是从S中的哪一个位置推过来的,记为\(c[i]\)。
我们从右向左遍历,如果遇到了连续字母段的尾部则停下,并且设这个位置为i。
接着我们可以把S中一个字符的移动轨迹视为一条折线,显然对于T中一段相同的字母段,是用同一条折线转移过来的。而我们的答案就是折线的横边个数,因为折线的纵线没有意义,而横线就是每次染到的位置。
我们考虑使用双端队列维护折线的每个横线的右端点,显然每时每刻队列中只会描述一个折线,而对于不同的折线,显然我们发现前面的折线先多拐一个弯(避开上一条折线),然后贴着后面的走,直到碰到某个字母段的最后一个字母停止,后面的不继承了。
如果出现了\(s[i]==t[i]\)的情况,那么我们把队列清空,把接下来要处理的折线放进队列,因为被\(s[i]==t[i]\) 隔开的东西是互不影响的(\(c[i]\)和i连线是不可能相交的)。
上幅图形象解释一下:

我们的目标是让一个折线到达某个字母连续段的最后一位,如果继承的折线已经超过了这个位置\(i\),那么后面的折线不会再有意义,直接舍去即可,舍去完之后把当前折线的终点(就是i)再pushback进去就是当前完整的折线。而且我们发现每个折线继承部分都是上一个折线的某一部分,但是由于上一个折线的作用,折线又不能相交,所以我们还是需要把新的折线多拐一次,即上面红线部分,在遇到右边折线的时候要拐一个弯,这个pushfront即可。(中间部分完全认为是原来折线+偏移量)
同时我们维护一个全局变量lz,表示遇到了多少个折线,作用就是我们可以快速计算某个折线由于前面折线而往左偏移了多少。因为我们发现每次继承的拐点正好左移一位。
每条折线的长度取max就是答案。
Code
代码其实还不到1K。
#include <bits/stdc++.h>
using namespace std;
char a[1000005],b[1000005];int n,ok,c[1000005],lz,ans,cnt;vector<int>v[30];deque<int>q;
int main()
{
scanf("%d%s%s",&n,a+1,b+1);c[n+1]=n+1;
for(int i=1;i<=n;i++) ok+=a[i]==b[i];
if(ok==n) return puts("0"),0;
if(n==1) return puts("-1"),0;
for(int i=1;i<=n;i++) v[a[i]-'a'].push_back(i);
for(int i=n;i;i--)
{
if(b[i]==b[i+1]&&i>=c[i+1]){c[i]=c[i+1];continue;}
else
{
while(!v[b[i]-'a'].empty()&&v[b[i]-'a'].back()>=c[i+1])
{
v[b[i]-'a'].pop_back();
if(v[b[i]-'a'].empty()) return puts("-1"),0;
}
c[i]=v[b[i]-'a'].back();
if(i>=c[i+1])
{
lz--;q.push_front(c[i+1]-lz-1);
while(q.back()+lz>=i) q.pop_back();
q.push_back(i-lz);
}
else{while(!q.empty()) q.pop_back();if(c[i]<i) q.push_back(i-lz);}
ans=max(ans,(int)q.size());
}
}
cout<<ans<<endl;
}
[agc007f] Shik and Copying String 模拟神题的更多相关文章
- hdoj5821【贪心-神题】
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,比赛的时候直接读错题了,实力带坑队友.... 题意: 有两个序列都代表筐,每个筐里只有一个球,然后序列的值代表筐里的球的颜色,问你在m次操作后,a序列的球能否变成b ...
- POJ 2014:Flow Layout 模拟水题
Flow Layout Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3091 Accepted: 2148 Descr ...
- HDOJ 2317. Nasty Hacks 模拟水题
Nasty Hacks Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...
- POJ 2484 A Funny Game(神题!)
一开始看这道博弈题的时候我就用很常规的思路去分析了,首先先手取1或者2个coin后都会使剩下的coin变成线性排列的长条,然后无论双方如何操作都是把该线条分解为若干个子线条而已,即分解为若干个子游戏而 ...
- BUAA 724 晴天小猪的神题(RMQ线段树)
BUAA 724 晴天小猪的神题 题意:中文题,略 题目链接:http://acm.buaa.edu.cn/problem/724/ 思路:对于询问x,y是否在同一区间,可以转换成有没有存在一个区间它 ...
- Bzoj 4408: [Fjoi 2016]神秘数 可持久化线段树,神题
4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 177 Solved: 128[Submit][Status ...
- SAC E#1 - 一道神题 Sequence1
题目背景 小强和阿米巴是好朋友. 题目描述 小强很喜欢数列.有一天,他心血来潮,写下了一个数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种:波动数列. 一个长度为n的波动数列满足对于任何i(1 < ...
- 【CF913F】Strongly Connected Tournament 概率神题
[CF913F]Strongly Connected Tournament 题意:有n个人进行如下锦标赛: 1.所有人都和所有其他的人进行一场比赛,其中标号为i的人打赢标号为j的人(i<j)的概 ...
- AtCoder 神题汇总
记录平时打 AtCoder 比赛时遇到的一些神题. Tenka1 Programmer Contest 2019 D Three Colors 题目大意 有 $n$ 个正整数 $a_1, a_2,\d ...
随机推荐
- 226. Invert Binary Tree 翻转二叉树
[抄题]: Invert a binary tree. 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 [暴力解法]: 时间分析: 空间分 ...
- spring4-2-bean配置-11-基于注解
- Linux 基金会宣布联合 edX 提供免费 Linux 课程
edX 是一个由麻省理工学院和哈佛大学创建的大规模开放在线课堂平台.它免费给大众提供大学教育水平的在线课堂.” edX 学习平台” 就像 开源软件似的发展,它使得其它院校机构也可以提供其高级学习的 ...
- Openssl gendsa命令
一.简介 gendsa命令能够根据DSA密钥参数生成DSA密钥 二.语法 openssl gendsa [-out filename] [-passout out] [-rand file(s)] [ ...
- 1710 生日蛋糕(1999 noi)
1710 生日蛋糕(1999 noi) 1999年NOI全国竞赛 题目描述 Description 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体 ...
- 根据dateutil计算从前到现在过去多少时间
import datetime from dateutil import relativedelta while 1: birthday = input(">>>" ...
- struts2标签使用详解
Struts2常用标签总结一 介绍1.Struts2的作用 Struts2标签库提供了主题.模板支持,极大地简化了视图页面的编写,而且,struts2的主题.模板都提供了很好的扩展性.实现了更好的代码 ...
- es-多文档简单查询(_mget)
1.多文档查询 (1)url:POST http://localhost:9200/_mget?pretty/ 参数: { "docs": [{ "_index" ...
- java Concurrent包学习笔记(二):CountDownLatch和CyclicBarrier
一.CountDownLatch CountDownLatch一个线程同步的工具,是的一个或者多个线程等待其他线程操作完成之后再执行. CountDownLatch通过一个给定的数值count来进行初 ...
- HDU 6096 String (AC自动机)
题意:给出n个字符串和q个询问,每次询问给出两个串 p 和 s .要求统计所有字符串中前缀为 p 且后缀为 s (不可重叠)的字符串的数量. 析:真是觉得没有思路啊,看了官方题解,真是好复杂. 假设原 ...