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. 索引(index)

    #创建索引 create index index_name_pass on student(name,pass); create index index_name_id on student(name ...

  2. spring jpa 创建时间和更新时间自动更新

    @Entity @Table(name="RS_SIGNUPUSER") public class RsSignUpUser { @Id @GenericGenerator(nam ...

  3. 【LA2238 训练指南】固定分区内存管理 【二分图最佳完美匹配,费用流】

    题意 早期的多程序操作系统常把所有的可用内存划分为一些大小固定的区域,不同的区域一般大小不同,而所有区域的大小之和为可用内存的大小.给定一些程序,操作系统需要给每个程序分配一个区域,使得他们可以同时执 ...

  4. Struts2概述

    -------------------siwuxie095 Struts2 概述 1.Struts2 是应用在 Java EE 三层架构中的 Web 层的框架 2.Struts2 是在 Struts1 ...

  5. Python——字典与字典方法

    字典是一种通过名字或者关键字引用的得数据结构,其键可以是数字.字符串.元组,这种结构类型也称之为映射.字典类型是Python中唯一內建的映射类型,基本的操作包括如下: (1)len():返回字典中键— ...

  6. Linux Virtualization with Xen

    Xen is the new virtualization kid on the block. It's gaining visibility and importance at a speed on ...

  7. devcloud

    zone名字:devcloud 外网dns:8.8.8.8 内网dns:10.0.2.3   提供点名称:devcloud   cs bug问题:https://issues.apache.org/j ...

  8. XSS的原理分析与解剖(第二篇)[转]

    0×01 前言: 上节(http://www.freebuf.com/articles/web/40520.html)已经说明了xss的原理及不同环境的构造方法.本期来说说XSS的分类及挖掘方法. 当 ...

  9. [C++] Virtual Destructor(虚析构函数)

    Without Virtual Destructor(虚析构函数) class A{ public: ; A() { cout <<"A()..."<< e ...

  10. [原创]SOUI GDI+渲染引擎下的字体特效,抛砖引玉

    由于SOUI是一种双渲染引擎的DUI库,默认在SKIA渲染引擎下是支持特效字体的,具体请参考DEMO中的源码. 但是使用GDI+渲染时是没有这些特效的,着实比较苦恼,此代抛砖引玉,细节实现 请自己再去 ...