【做题】CF119D. String Transformation——KMP
题意:有两个字符串\(a,b\),下标从\(0\)开始。求数对\((i,j)\)满足\(a[i+1:j] + r(a[j:n]) + r(a[0:i+1]) = b\),其中\(r(s)\)表示字符串\(s\)的反串。若有多组解,输出其中\(i\)最大,然后\(j\)尽可能小的一组。
\(|a|,|b| \leq 10^6\)
首先考虑枚举\(i\)。那么,我们就要让\(a[i+1:j] + r(a[j:n]) = b[0:n-i-1]\)。因此,前面的\(a[i+1:j]\)必须是\(b\)的一个前缀。这个限制比较简单,求出最长公共前缀后,就可以转化为\(j \leq r\)的形式。
接下来,我们得满足\(r(a[j:n])\)是\(b[0:n-i-1]\)的一个后缀。并且,我们只要求出满足这个条件的最小的\(j\)就可以了。也就是求出\(a\)最长的后缀,它在翻转后也是\(b[0:n-i-1]\)的后缀。这个问题比较复杂,要进行化简。先解决翻转。记\(a_r\)为\(a\)的反串,那么,问题就成为求最长的\(a_r\)的前缀,它也是\(b[0:n-i-1]\)的后缀。开始于一个固定位置的前缀,结束于多个不同位置的后缀。仔细一想的话,这正是KMP中nex数组的定义。因此,我们把\(a_r\)和\(b\)连起来(分隔符还是要加的),求一遍nex数组就可以了。
顺便一提,最长公共前缀必须用EXKMP来求,不然会T。
时间复杂度\(O(n)\)。
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
char a[N],b[N],s[N << 1];
int nex[N << 1],n,pre[N << 1],pw[N],ans1,ans2;
int main() {
cin.getline(a+1,N);
cin.getline(b+1,N);
if (strlen(a+1) != strlen(b+1)) {
puts("-1 -1");
return 0;
}
n = strlen(a+1);
for (int i = 1 ; i <= n ; ++ i)
s[i] = a[n - i + 1];
s[n+1] = 0;
for (int i = 1 ; i <= n ; ++ i)
s[i + n + 1] = b[i];
nex[0] = -1;
for (int i = 1, j = -1 ; i <= (n << 1) + 1 ; nex[i++] = ++ j)
while (j >= 0 && s[i] != s[j+1]) j = nex[j];
for (int i = 1 ; i <= n ; ++ i)
s[i] = b[i];
s[n+1] = 0;
for (int i = 1 ; i <= n ; ++ i)
s[i + n + 1] = a[i];
pre[1] = 2 * n + 1;
while (s[2 + pre[2]] == s[1 + pre[2]] && 2 + pre[2] <= 2 * n + 1)
++ pre[2];
int p = 2;
for (int i = 3 ; i <= 2 * n + 1 ; ++ i) {
if (pre[i - p + 1] < pre[p] + p - i)
pre[i] = pre[i - p + 1];
else {
int j = max(0,p + pre[p] - i);
while (s[i + j] == s[1 + j] && i + j <= 2 * n + 1)
++ j;
pre[i] = j;
p = i;
}
}
ans1 = ans2 = -1;
for (int i = 1 ; i <= n ; ++ i) {
int r = pre[i + n + 1] + i;
int l = nex[2 * n + 1 - (i-1)];
if (n - l + 1 <= r) ans1 = i - 2, ans2 = n - l;
if (a[i] != b[n-i+1]) break;
}
if (ans1 == -1) ans2 = -1;
printf("%d %d\n",ans1,ans2);
return 0;
}
小结:这道题难度其实不大,但推导过程较长,因此需要时刻保持思路清晰,心态平稳。
【做题】CF119D. String Transformation——KMP的更多相关文章
- [日记&做题记录]-Noip2016提高组复赛 倒数十天
写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...
- SDOI2016 R1做题笔记
SDOI2016 R1做题笔记 经过很久很久的时间,shzr终于做完了SDOI2016一轮的题目. 其实没想到竟然是2016年的题目先做完,因为14年的六个题很早就做了四个了,但是后两个有点开不动.. ...
- CCPC2018-湖南全国邀请赛 G String Transformation
G.String Transformation 题目描述 Bobo has a string S = s1 s2...sn consists of letter a , b and c . He ca ...
- LCT做题笔记
最近几天打算认真复习LCT,毕竟以前只会板子.正好也可以学点新的用法,这里就用来写做题笔记吧.这个分类比较混乱,主要看感觉,不一定对: 维护森林的LCT 就是最普通,最一般那种的LCT啦.这类题目往往 ...
- java做题笔记
java做题笔记 1. 初始化过程是这样的: 1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化: 2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序 ...
- NOIP做题练习(day2)
A - Reign 题面 题解 最大子段和+\(DP\). 预处理两个数组: \(p[i]\)表示 \(i\) 之前的最大子段和. \(l[i]\)表示 \(i\) 之后的最大子段和. 最后直接输出即 ...
- SAM 做题笔记(各种技巧,持续更新,SA)
SAM 感性瞎扯. 这里是 SAM 做题笔记. 本来是在一篇随笔里面,然后 Latex 太多加载不过来就分成了两篇. 标 * 的是推荐一做的题目. trick 是我总结的技巧. I. P3804 [模 ...
- UOJ 做题记录
UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...
- C语言程序设计做题笔记之C语言基础知识(下)
C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...
随机推荐
- (1)打造简单OS-汇编写入引导区,虚拟机启动步骤
首先需要您在网上下载NASM编译器,可以将汇编编译为二进制文件 1.写一段汇编代码在屏幕上打印一段字符,可以运行的!并进行nasm为二进制文件,如下"test.asm" 该段汇编主 ...
- Discuz!代码大全
1.[ u]文字:在文字的位置可以任意加入您需要的字符,显示为下划线效果. 2.[ align=center]文字:在文字的位置可以任意加入您需要的字符,center位置center表示居中,left ...
- 重建二叉树POJ2255
重建二叉树 给定一棵二叉树的前序遍历和中序遍历的结果,求其后序遍历. 输入输入可能有多组,以EOF结束.每组输入包含两个字符串,分别为树的前序遍历和中序遍历.每个字符串中只包含大写字母且互不重复.输出 ...
- html5-表单和input元素用法
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- uvalive 3415 Guardian Of Decency
题意: 有一个老师想组织学生出去旅游,为了避免他们之间有情侣产生,他制定了一系列的条件,满足这些条件之一,那么这些人理论上就不会成为情侣: 身高相差40cm:性别相同:喜欢的音乐风格不同:最喜欢的运动 ...
- 【Hadoop学习之五】win7+Eclipse+hadoop3搭建本机开发环境
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 拓扑: 知识准备: 1.eclip ...
- python实现堆栈和队列
利用python列表实现堆栈和队列 堆栈: 堆栈是一个后进先出的数据结构,其工作方式就像生活中常见到的直梯,先进去的人肯定是最后出. 我们可以设置一个类,用列表来存放栈中的元素的信息,利用列表的app ...
- 分布式系统ID生成方案
自增ID 不错,可以限度抑制ID的大小.但需要有一个中心化的节点作为解决原子性问题.可以选用Redis,MySQL,Zookeeper.成本有点高. UUID 分布式,而且唯一!缺点是生产的ID太长. ...
- (Review cs231n) Backpropagation and Neural Network
损失由两部分组成: 数据损失+正则化损失(data loss + regularization) 想得到损失函数关于权值矩阵W的梯度表达式,然后进性优化操作(损失相当于海拔,你在山上的位置相当于W,你 ...
- 创建一个简单的WCF程序
1.创建WCF服务库 打开VS2010,选择文件→新建→项目菜单项,在打开的新建项目对话框中,依次选择Visual C#→WCF→WCF服务库,然后输入项目名称(Name),存放位置(Location ...