【65测试20161114】【字符串】【DP】
第一题 复制&粘贴:
文件的内容是一个字符串S,对其进行N次复制&粘贴的操作,第i次操作复制位置Ai和位置Bi之间的所有文字,然后在位置Ci粘贴。这里位置x表示字符串的第x个字符的后面那个位置(位置0表示字符串的开头),例如字符串”copypaste”的位置6表示字符’a’和字符’s’之间的位置,位置9表示’e’后面的位置(即字符串的结尾)。不过,如果操作后的字符串长度超过了M,那么将超过的部分删除,只保留长度为M的前缀。
你的任务是写一个程序,输出N次操作后字符串的前K个字符。
对于40%的数据,N,M<=2000
对于100%的数据:
1<=K<=200
1<=M<=10^9
S 的每个字符都是小写字母(‘a’~’z’)
K<=|S|<=min(M,2*10^5)
1<=N<=2*10^5
设第i 次操作前的字符串长度为Li,那么0<=Ai<Bi<=Li 且0<=Ci<=Li (1<=i<=N)
解:
40% :直接模拟,s.insert(), s.erase()就可以了。
100%:考虑到k的值很小,所以我们只需要知道前k个字符对应的在原字符串的位置就可以了。用ans[i]先表示第i 个位置的字符在最后修改后字符串的位置,然后一步步的推回原字符串的位置。因为最后ans[i]=i;所以从最后一个操作开始,枚举每个前k个位置,有三种情况:
1、如果x位置是在这个操作的c前面,对x位置没有影响;
2、x位置是由这个操作粘贴过来的,则粘贴前x位置的字符的位置在x-c[i]+a[i];
3、如果在这个操作的c[i]+b[i]-a[i]后,则x位置的字符为右移后得到的,则原位置为:x-(b[i]-a[i]).
这样一直递推到第一个操作,ans[]所指的位置为原字符串的对应位置。(毕竟以后得到的所有字符都是由原字符串复制粘贴得到的)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200005
using namespace std;
int k,m,n,ans[];
int a[maxn],b[maxn],c[maxn];
char s[maxn];
int main()
{
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
cin>>k>>m;
scanf("%s",s+);
cin>>n;
for (int i=;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
for (int i=;i<=k;i++)
ans[i]=i;//在第i位置的字符在哪个位置
for (int i=n;i>=;i--)
for (int j=;j<=k;j++)
{
if (ans[j]<=c[i]) continue;//< = 在c[i]前面没有影响
else if (ans[j]<=c[i]+b[i]-a[i])//粘贴过来的 ,还原为原位置
ans[j]=ans[j]-c[i]+a[i];
else ans[j]-=b[i]-a[i];//右移后的,还原为原位置
}
for (int i=;i<=k;i++)
putchar(s[ans[i]]);//putchar 的使用
return ;
}
第二题:愉快的logo设计
设计一个用’J’,’O’,’I’三种文字环形排列的logo。
如下所示,对于任意非负整数k,我们定义标号为k的JOI序列Sk为:
·S0为’J’,’O’,’I’中任一字符构成的长度为1的字符串
·S[k+1]为最初4^k个字符都是’J’,接下来的4^k个字符都是’O’,接下来的4^k个字符都是’I’,最后4^k个字符是字符串Sk的长为4^(k+1)的字符串
现在,K理事长在纸上写下了由4^K个文字构成的一个环形字符串,字符串中每个字符都是’J’,’O’,’I’中的一个。K理事长想要修改一些文字,使得得到的字符串从某个起点开始顺时针读一圈后可以得到SK。在满足条件的情况下,要求修改的文字数量最少。
【Sample Input】
2
JJOIJJOJOIOJOOOI
【Sample Output】
7
【HINT】

从○标记的位置顺时针阅读一圈得到“JJJJOOOOIIIIJOIJ”,满足S2的条件,且修改文字数达到最小值7。
【Data Constraint】
对于30%的数据,1<=K<=5
对于100%的数据,1<=K<=10
解:(读题都读了好久才读懂)
30%:直接挨个比较就可以了。
100%:考虑到目标字符串很有规律,是一段一段的重复的:
4^(k-1)个J,4^(k-1)个O,4^(k-1)个I,4^(k-2)个J,4^(k-2)个O,4^(k-2)个I,..........4^0个J,4^0个O,4^0个I,最后一个随意。
所以可以换一个角度去想这个问题。我们普通的思路是用原字符串来匹配目标字符串,而根据刚才的规律,我们可以换为用目标字符串来匹配原字符串。具体的操作如下:
第一次匹配:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| J | J | J | J | O | O | O | O | I | I | I | I | J | O | I | J |
| J | J | O | I | J | J | O | J | O | I | O | J | O | O | O | I |
第二次匹配:(目标串右移)
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | |
| J | J | J | J | O | O | O | O | I | I | I | I | J | O | I | X | |
| J | J | O | I | J | J | O | J | O | I | O | J | O | O | O | I | J |
第三次匹配:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ||
| J | J | J | J | O | O | O | O | I | I | I | I | J | O | I | X | ||
| J | J | O | I | J | J | O | J | O | I | O | J | O | O | O | I | J | J |
等等........
所以原串要*2。 O(4^N*K)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1200005
using namespace std;
int k,f[(maxn<<)][],n,ki,ans=;
char c[(maxn<<)];
int main()
{
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
cin>>k;
n=(<<(k<<));
for (int i=;i<=n;i++)
{
char s=getchar();
while (s!='J'&&s!='O'&&s!='I') s=getchar();
c[i]=s;c[i+n]=s;
}
for (int i=;i<=(n<<);i++)//前缀和
{
f[i][]=f[i-][];
f[i][]=f[i-][];
f[i][]=f[i-][];
if (c[i]=='J') f[i][]++;
else if (c[i]=='O') f[i][]++;
else f[i][]++;
}
ki=(<<((k-)<<));
for (int i=;i<=n;i++)
{
int cur=ki,sum=,tmp=i;
while (cur)
{
sum+=f[tmp+cur-][]-f[tmp-][];
sum+=f[tmp+cur*-][]-f[tmp+cur-][];
sum+=f[tmp+cur*-][]-f[tmp+*cur-][];
tmp+=cur*;
cur=(cur>>);
}
ans=min(ans,n-sum-);
}
printf("%d",ans);
return ;
}
【65测试20161114】【字符串】【DP】的更多相关文章
- 【BZOJ 2121】 (字符串DP,区间DP)
2121: 字符串游戏 Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对于一个在集合S中的字符串p,如果p在L中出现,B ...
- AtCoder Regular Contest 081 E - Don't Be a Subsequence(字符串DP)
引用自:onion_cyc 字符串DP一直不是强项...以后没思路的题就想DP和网络流23333333 f[i]表示从i开始的后缀非子序列的最短长度 pos[i][j]表示从i开始的j字符最早出现位 ...
- NOIP2015Day2T2子串(字符串dp)
又被“if(a=b)”坑了QAQ...写C++还是得开Warning,这么久了pascal还没改过来咋回事啊QWQ 题目大意就不说了OWO 网上的题解都不怎么看得懂啊...好像写得都很乱?还是我太sb ...
- Codeforces 1150D(字符串dp)
反思 三维的dp压根没看出来,看题解以后思路又很直观,找几道字符串dp练练才行 序列自动机和优化一维略 /* __ __ * ____| |_____| |____ * | | * | __ | * ...
- fzu2172 字符串dp
F - 巡了南山我巡北山 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...
- 51nod 1092 回文字符串 (dp)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1092 这个题是poj-3280的简化版,这里只可以增加字符,设 dp[i ...
- Codeforces Round #358 (Div. 2) D. Alyona and Strings 字符串dp
题目链接: 题目 D. Alyona and Strings time limit per test2 seconds memory limit per test256 megabytes input ...
- 【转】shell学习笔记(三)——引用变量、内部变量、条件测试、字符串比较、整数比较等
1.env显示当前的环境变量 2.PS1='[\u@\h \w \A] \$' 可以设置bash的命令与提示符. 3.echo $$ 显示当前bash的PID号 4.echo $?显示上一条指令的回传 ...
- NYOJ37-回文字符串(dp)
37-回文字符串 内存限制:64MB 时间限制:3000ms 特判: No通过数:88 提交数:177 难度:4 题目描述: 所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如& ...
随机推荐
- JavaScript对象的chapterI
对象: 对象就是由一些彼此相关的属性和方法集合在一起而构成的一个数据实体. 一.本地对象: 1.Date——日期对象 var myDate = new Date(); myDate.getFullYe ...
- Qt设计师学习笔记--Sharping-Changing Dialogs
1.pushbutton->default属性为true,按回车相当于点击该按钮. 2.选中checkable后,Button变成切换按钮(toggle button),可以有两种状态:按下/弹 ...
- Linux服务器的那些性能参数指标
Linux服务器的那些性能参数指标 一个基于Linux操作系统的服务器运行的同时,也会表征出各种各样参数信息.通常来说运维人员.系统管理员会对这些数据会极为敏感,但是这些参数对于开发者来说也十分重要, ...
- js设计模式总结-策略模式
策略模式 要解决的问题 当解决一个问题有多种方法时,选择使用哪种方法时就少不了要用大量的if语句进行判断,如果将这些方法的实现和判断语句放在一起实现就会产生问题, 比如增加一种的新的方法时,就不得不再 ...
- Linux C++线程池
.为什么需要线程池? 部分应用程序需要执行很多细小的任务,对于每个任务都创建一个线程来完成,任务完成后销毁线程,而这就会产生一个问题:当执行的任务所需要的时间T1小于等于创建线程时间T2和销毁线程时间 ...
- Openfire用户密码加密解密
需求要求审核过程中都用匿名进行用户注册登录,注册用户审核通过后才使用openfire内置表 如何做到用户密码统一 Openfire是通过org.jivesoftware.util.Blowfish.j ...
- 转载ali面
引言 首先声明,不要再问LZ谁是林萧,林萧就是某著名程序员小说的主角名字. 写这篇文章的目的其实很简单,算是对之前LZ一篇文章的补充和完善. 之前LZ写过一篇<回答阿里社招面试如何准备,顺便谈谈 ...
- git 使用 总结
比较好的教程 http://backlogtool.com/git-guide/cn/intro/intro1_2.html 1.git流程图 2.git 新建仓库 git init git clon ...
- HBase 安装
HBase 集群安装 1.上传tar包,解压tar包 tar -zxvf hbase-1.1.5-bin.tar.gz 2.修改配置文件 进入 hbase/conf/ 在文件 regionserve ...
- H5 学习笔记(一、关于position定位)
主要是relative与absolute的用法: 1.relative 依据left right top bottom 等属性在正常文档流中脱离位置,即相对于他的正常文档流位置进行移动.两个都为rel ...