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. Hibernate其它API

    ----------------siwuxie095 (一)Query 1.使用 Query 对象执行查询操作,不需要写 sql 语句,但是要写 hql 语句 (1)hql:即 Hibernate Q ...

  2. iOS导航栏自由缩放头像效果

    效果图: 上代码: 先给一个self.navigationItem.titleView ,然后再放个ImangeView添加到titleView上: UIView *titleView = [[UIV ...

  3. 用 Markdown 写作(一)——添加文章页内导航

    Markdown 可以用更简化的标记来写文章,基本的语法可以参考Markdown 语法说明 (简体中文版). 我平时很少按照论文的写法去写博客,说来忏愧,因为很少写技术性的文章,最近看到百度百科和很多 ...

  4. Spring中通配符(转)

    一.加载路径中的通配符:?(匹配单个字符),*(匹配除/外任意字符).**/(匹配任意多个目录) classpath:app-Beans.xml 说明:无通配符,必须完全匹配   classpath: ...

  5. [C++] * Basic and Class

    C++ 目  录 1 开始学习C++ 4 1.1 C++的头文件 4 1.2 命名空间 4 1.3 更严格的类型转化 4 1.4 new和delete 4 1.5 内联函数 4 1.6 引用 5 1. ...

  6. mariadb主从备份

    mariadb主从备份 master主库配置 停止mariadb systemctl stop mariadb 修改配置文件my.conf vim /etc/my.cnf [mysqld] serve ...

  7. Linux Mint 17使用配置

    => 调亮度: 方法一: 每次开机或注销登录之后需要重新设置 > /sys/class/backlight/intel_backlight/brightness #根据自己需要调值,如20 ...

  8. myeclipse如何将项目打包成war包

    打包步骤如下: 详细介绍请查看全文:https://cnblogs.com/qianzf/ 原文博客的链接地址:https://cnblogs.com/qzf/

  9. Ubuntu14.04 下安装Samba服务

    1.更改linux镜像源: # vim /etc/apt/sources.list deb http://mirrors.163.com/ubuntu/ trusty main restricted ...

  10. Centos7下安装与卸载Jdk1.8

    安装 去官网下载jdk:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 使用xs ...