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 模拟神题的更多相关文章

  1. hdoj5821【贪心-神题】

    啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,比赛的时候直接读错题了,实力带坑队友.... 题意: 有两个序列都代表筐,每个筐里只有一个球,然后序列的值代表筐里的球的颜色,问你在m次操作后,a序列的球能否变成b ...

  2. POJ 2014:Flow Layout 模拟水题

    Flow Layout Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3091   Accepted: 2148 Descr ...

  3. HDOJ 2317. Nasty Hacks 模拟水题

    Nasty Hacks Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  4. POJ 2484 A Funny Game(神题!)

    一开始看这道博弈题的时候我就用很常规的思路去分析了,首先先手取1或者2个coin后都会使剩下的coin变成线性排列的长条,然后无论双方如何操作都是把该线条分解为若干个子线条而已,即分解为若干个子游戏而 ...

  5. BUAA 724 晴天小猪的神题(RMQ线段树)

    BUAA 724 晴天小猪的神题 题意:中文题,略 题目链接:http://acm.buaa.edu.cn/problem/724/ 思路:对于询问x,y是否在同一区间,可以转换成有没有存在一个区间它 ...

  6. Bzoj 4408: [Fjoi 2016]神秘数 可持久化线段树,神题

    4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 177  Solved: 128[Submit][Status ...

  7. SAC E#1 - 一道神题 Sequence1

    题目背景 小强和阿米巴是好朋友. 题目描述 小强很喜欢数列.有一天,他心血来潮,写下了一个数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种:波动数列. 一个长度为n的波动数列满足对于任何i(1 < ...

  8. 【CF913F】Strongly Connected Tournament 概率神题

    [CF913F]Strongly Connected Tournament 题意:有n个人进行如下锦标赛: 1.所有人都和所有其他的人进行一场比赛,其中标号为i的人打赢标号为j的人(i<j)的概 ...

  9. AtCoder 神题汇总

    记录平时打 AtCoder 比赛时遇到的一些神题. Tenka1 Programmer Contest 2019 D Three Colors 题目大意 有 $n$ 个正整数 $a_1, a_2,\d ...

随机推荐

  1. 创建excel,合并单元格,设置单元格样式

    package com.huawei.excel; import java.io.File;import java.io.FileOutputStream;import java.util.Date; ...

  2. 使用RampTexture来控制diffuse shading

    [RampTexture] RampTexture(渐变纹理),可以是1D/2D纹理. This allows you to accentuate the surface's colors to fa ...

  3. 实现SwipeRefreshLayout首次进入自动刷新

    看到了Android版知乎实现了这种效果,就自己也实现了一下. 先来一张效果图 实现方式: 方法一. ①在onWindowFocusChanged()方法中,设置为刷新状态为true @Overrid ...

  4. 每天一个Qt类之QWidget

    每天一个Qt类之QWidget QWidget类是所有用户界面对象的基类 继承QObject和QPaintDevice 被QButton.QFrame.QDialog.QComboBox.QDataB ...

  5. EZOJ #227

    传送门 分析 我们发现第一段数和最后一段数对答案的贡献系数为1/-1,其余为0/2/-2 而且对于相邻两段不能系数均非0 于是可以dp 代码 #include<iostream> #inc ...

  6. tornado异步请求非阻塞-乾颐堂

    前言 也许有同学很迷惑:tornado不是标榜异步非阻塞解决10K问题的嘛?但是我却发现不是torando不好,而是你用错了.比如最近发现一个事情:某网站打开页面很慢,服务器cpu/内存都正常.网络状 ...

  7. vim调用替换文件内容

    :s/vivian/sky/ 替换当前行第一个 vivian 为 sky    :s/vivian/sky/g 替换当前行所有 vivian 为 sky    :n,$s/vivian/sky/ 替换 ...

  8. hdu 1686 KMP算法

    题意: 求子串w在T中出现的次数. kmp算法详解:http://www.cnblogs.com/XDJjy/p/3871045.html #include <iostream> #inc ...

  9. 实践作业3:白盒测试----第三次小组会DAY8

    我们小组于12月11日在东九教学楼召开了会议,小组第二次会议中就讨论了被测系统中风险最高的模块,于是选择管理员的教师添加模块,针对代码展开静态评审.这一次会议,小组主要讨论了应该从哪些方面来测评代码的 ...

  10. data cleaning

    Cleaning data in Python   Table of Contents Set up environments Data analysis packages in Python Cle ...