题目

题目大意

给你一个文本,要删去其中所有的‘e’。

有三种操作:

  • h光标左移。
  • x删除光标上面的字母(光标是横着的)。
  • fc跳到后面的第一个字符为‘c’的位置。

问操作序列的最短长度。


思考历程

首先看错了题意,然后感觉似乎很水……后来发现错了……

接下来开始想其它的方法。

有个还不错的思路:设\(f_{i,j}\)表示前面\(i\)个‘e’被选了,现在光标在\(j\)的最小答案。

比赛的时候头昏眼花写出了一个\(O(n^4)\)的转移方程,后来在最后5分钟的时候发现其中的一对变量是重复的……也就是说,实际上是\(O(n^3)\)……

我就这么错过了50分……

(后来才知道,同样是这个状态,可以优化到\(O(10n^2)\),具体不再赘述)


正解

先推荐一篇博客:https://www.cnblogs.com/Itst/p/10339605.html

这篇博客非常详细。所以我觉得我不用说这么多了。

这题的正解是个看起来高大上的线头DP

什么是高大上?就是名字都没听过的东西。

先说一开始的操作:将所有的‘e’删掉,答案预先加上\(2\)倍的‘e’的个数。具体原因显然。

那么必经位置就是原先前面是‘e’的位置。

题目转化为:从头开始,每次可以进行两种操作,问经过所有必经位置的最小答案。

我们形象地将文本看作一个数轴,每次的操作看作走一条边,往后跳的称作飞边,往前跳的称作走边

开始设DP状态:

\(f_{i,j}\)表示\(i\)和\(i+1\)之间的垂线与走过的边有一个交点,显然这是和飞边的交点。\(j\)为飞边落下位置上的字母;

\(g_{i,j,k}\)表示垂线与走过的边有三个交点,显然这是和两个飞边和一个走边的交点。\(j\)为前面一条飞边落下位置上的字母,\(k\)为后面一条飞边落下位置的字母。

可能有点不清楚,那我就借一下刚刚那片博客的图:



先考虑\(f_{i,j}\)的转移,有以下四种情况:

  1. \(f_{i-1,j}\),\(s_i\neq j\)且\(i\)不是必经点。
  2. \(f_{i-1,s_i}+2\)
  3. \(g_{i-1,s_i,j}\),\(s_i\neq j\)
  4. \(g_{i-1,s_i,s_i}+2\)

画画图就能理解了……再次借用图片。

再考虑\(g_{i,j}\)的转移,有以下六种情况(方程和别人的有很大区别,不要混淆了)。

(\(nex_{i,j}\)表示\(i\)后第一个\(j\)的位置)

  1. \(f_{i-1,j}+nex_{i,j}-i+2\),\(j\neq s_i\)
  2. \(f_{i-1,s_i}+nex_{i,j}-i+4\)
  3. \(g_{i-1,j,k}\),\(j\neq s_i\)且\(k \neq s_i\)
  4. \(g_{i-1,s_i,k}+nex_{i,j}-i+2\),\(k\neq s_i\)
  5. \(g_{i-1,j,s_i}+2\),\(j\neq s_i\)
  6. \(g_{i-1,s_i,s_i}+nex_{i,j}-i+4\)

这些图片当然也是我Copy过来的,不过要注意的是,我的转移中\(i+1\)和\(j\)是已经连在一起的。

原版的方程看别人博客去……(其实我之前一直不理解为什么他们不把\(i+1\)和\(j\)连在一起,后来我终于明白,它们的状态计算的答案是\(i\)之前的,后面的还没有算。在后面的转移过程中会慢慢累加,补整齐。不过我觉得我这样打好理解一点)

方程完了,剩下一点细节:初始化\(f_{0,s_1}=0\),其它为无限大;答案加上\(f_{n,'k'}\),'k'为原串中没有出现过的字符。这相当于最后连一条出去(所以还要再减\(2\))。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 70010
inline void update(int &a,int b){a>b?a=b:0;}
int _n,n;
char _s[N],s[N];
int nex[N][11];
bool must[N];
int f[N][11],g[N][11][11];
int ans;
int main(){
scanf("%d%s",&_n,_s+1);
ans=0;
for (int i=1;i<=_n;++i)
if (_s[i]=='e')
ans+=2;
else{
s[++n]=_s[i];
if (_s[i-1]=='e')
must[n]=1;
}
memset(nex[n+1],1,sizeof nex[n+1]);
s[n+1]='k';
for (int i=1;i<=n+1;++i)
s[i]-='a';
for (int i=n;i>=1;--i){
memcpy(nex[i],nex[i+1],sizeof nex[i]);
nex[i][s[i+1]]=i+1;
}
memset(f,127,sizeof f);
memset(g,127,sizeof g);
f[0][s[1]]=0;
for (int i=1;i<=n;++i){
for (int j=0;j<=10;++j){
if (j!=s[i]){
if (!must[i])
update(f[i][j],f[i-1][j]);
update(f[i][j],g[i-1][s[i]][j]);
}
update(f[i][j],f[i-1][s[i]]+2);
update(f[i][j],g[i-1][s[i]][s[i]]+2);
}
for (int j=0;j<=10;++j)
for (int k=0;k<=10;++k){
if (j!=s[i]){
update(g[i][j][k],f[i-1][j]+nex[i][j]-i+2);
if (k!=s[i])
update(g[i][j][k],g[i-1][j][k]);
update(g[i][j][k],g[i-1][j][s[i]]+2);
}
update(g[i][j][k],f[i-1][s[i]]+nex[i][j]-i+4);
if (k!=s[i])
update(g[i][j][k],g[i-1][s[i]][k]+nex[i][j]-i+2);
update(g[i][j][k],g[i-1][s[i]][s[i]]+nex[i][j]-i+4);
}
}
ans+=f[n][10]-2;
printf("%d\n",ans);
return 0;
}

总结

见到毒瘤题的时候要仔细找找题目的性质……

DP时要善于分类讨论……不要被高大上的名字吓到了……

[JZOJ3320] 【BOI2013】文本编辑器的更多相关文章

  1. 富文本编辑器Simditor的简易使用

    最近打算自己做一个博客系统,并不打算使用帝国cms或者wordpress之类的做后台管理!自己处于学习阶段也就想把从前台到后台一起谢了.好了,废话不多说了,先来看看富文本编辑器SimDitor,这里是 ...

  2. 个人网站对xss跨站脚本攻击(重点是富文本编辑器情况)和sql注入攻击的防范

    昨天本博客受到了xss跨站脚本注入攻击,3分钟攻陷--其实攻击者进攻的手法很简单,没啥技术含量.只能感叹自己之前竟然完全没防范. 这是数据库里留下的一些记录.最后那人弄了一个无限循环弹出框的脚本,估计 ...

  3. 关于SMARTFORMS文本编辑器出错

    最近在做ISH的一个打印功能,SMARTFORM的需求本身很简单,但做起来则一波三折. 使用环境是这样的:Windows 7 64bit + SAP GUI 740 Patch 5 + MS Offi ...

  4. 基于trie树的具有联想功能的文本编辑器

    之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...

  5. UEditor百度富文本编辑器--让编辑器自适应宽度的解决方案

    UEditor百度富文本编辑器的initialFrameWidth属性,默认值是1000. 不能够自适应屏幕宽度.如图1: 刚开始的时候,我是直接设置initialFrameWidth=null的.效 ...

  6. [bzoj1269][AHOI2006文本编辑器editor] (splay模版题 or pb_ds [rope]大法)

    Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或 ...

  7. Bzoj1269 [AHOI2006]文本编辑器editor

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3678  Solved: 1380 Description 这些日子,可可不和卡卡一起玩了,原来可可正 ...

  8. PHP Ueditor 富文本编辑器

    2016年12月11日 08:46:59 星期日 百度的简版富文本编辑器umeditor很久没更新了 全功能版本的配置项跟umeditor还是有区别的, 这里说下ueditor怎么对接到项目中去, 主 ...

  9. js中的文本编辑器控件KindEditor---那些打酱油的日子

    使用文本编辑器控件KindEditor渲染文本域页面显示 this.sync()同步KindEditor的值到textarea文本框 editor.isEmpty()判断文本域是否是空 editer. ...

  10. Unix及类Unix系统文本编辑器的介绍

    概述 Vim是一个类似于Vi的著名的功能强大.高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性.VIM是纯粹的自由软件. Vim普遍被推崇为类Vi编辑器中最好的一个,事实上真正的劲敌来自Em ...

随机推荐

  1. 8、如何实现可迭代对象和迭代器对象 9、如何使用生成器函数实现可迭代对象 10、如何进行反向迭代以及如何实现反向迭代 11、如何对迭代器做切片操作 12、如何在一个for语句中迭代多个可迭代对象

    8.如何实现可迭代对象和迭代器对象 PS:注意重载Iterator方法的时候,需要和原来的方法名一样,否则创建实例时会报错 from collections import Iterator,Itera ...

  2. ubuntu QT安装以及配置交叉编译环境

    我的环境:ubuntu14.04  64位 1.下载Qt: 上网搜索 qt-opensource-linux-x64-5.3.0.run下载有好多百度云盘 要么在官网下载追新版本http://down ...

  3. ros语音交互(五)移植科大讯飞语音识别到ros

    将以前下载的的语音包的 samples/iat_record/的iat_record.c speech_recognizer.c speech_recognizer.c 拷贝到工程src中, linu ...

  4. 浏览器http跳转至https问题

    Chrome 浏览器 地址栏中输入 chrome://net-internals/#hsts 在 Delete domain security policies 中输入项目的域名,并 Delete 删 ...

  5. quartz的使用(二.基本过程)

    1.关于各个要素的创建,SchedulerFactoryBean,CronTriggerFactoryBean及JobDetailFactoryBean全部实现spring中的FactoryBean& ...

  6. Interview - 面试题汇总目录

    参考 java 入门面试题 https://blog.csdn.net/meism5/article/details/89021536 一.Java 基础 1.JDK 和 JRE 有什么区别? 2.= ...

  7. 配置类一@Configuration

    import org.springframework.context.annotation.Configuration; @Configuration用于定义配置类,可替换xml配置文件,被注解的类内 ...

  8. thinkphp环境要求

    框架本身没有什么特别模块要求,具体的应用系统运行环境要求视开发所涉及的模块.ThinkPHP底层运行的内存消耗极低,而本身的文件大小也是轻量级的,因此不会出现空间和内存占用的瓶颈. PHP版本要求 P ...

  9. NX二次开发-UFUN批量操作图层状态UF_LAYER_set_many_layers_status

    NX11+VS2013 #include <uf.h> #include <uf_ui.h> #include <uf_layer.h> UF_initialize ...

  10. 去除springboot内置tomcat

    /** * @author zx * @title: ServletInitializer * @projectName activiti * @description: 解决内置tomcat * @ ...