题目

题目大意

给你一个文本,要删去其中所有的‘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. JSON数组对象和JSON字符串的转化,map和JSON对象之间的转化

    这种用法包括前端和后端: 前端: 1. 转化为JSON对象方便操作 var jsonObj = JSON.parse(str); 得到的是一个json数组对象,可以通过 for (var p in j ...

  2. Unity中调用Windows窗口句柄以及根据需求设置并且解决扩展屏窗体显示错乱/位置错误的Bug

    问题背景: 现在在搞PC端应用开发,我们开发中需要调用系统的窗口以及需要最大化最小化,缩放窗口拖拽窗口,以及设置窗口位置,去边框等功能 解决根据: 使用user32.dll解决 具体功能: Unity ...

  3. kernel32 的 GetVersionExA/W

    今天接到一个问题,说Kernel32 模块的 GetVersionEx 获取系统版本不准确, 然后让我查查什么原因, 我当时就想,它不准,就用ntdll的 RtlGetVersion 阿,或者 Rtl ...

  4. Vue之获取用户当前所在省市

    今天小编给大家带来的是使用Vue获取用户所在城市,Vue是很强大的,给大家准备好现成的插件供大家调用,下面的Demo小编使用的是百度API. 首先我们从百度平台申请百度地图的秘钥,申请成功后我们将&l ...

  5. yum处理损坏的包依赖关系

    有时在安装多个软件包时,某个包的软件依赖关系可能会被另外一个包的安装覆盖掉.这叫做损坏的包依赖关系(broken dependency). 如果系统出现问题,可以先尝试: yum clean all ...

  6. c++ const (转)

    在C++的类定义里面,可以看到类似下面的定义: class List { private: Node * p_head; int length; …… Public: int GetLength () ...

  7. Visio2016专业版永久激活码

    Visio2016专业版永久激活码: [Key]:NKVJM-8MTT4-8YDFR-6738M-DPFJH [Key]:W9WC2-JN9W2-H4CBV-24QR7-M4HB8 [Key]:7K8 ...

  8. CSIC_716_20191207【并发编程---进程与线程】

    僵尸进程与孤儿进程 ........... 守护进程 from Multiprocessing  import Process 在 suboprocess.start( ) 的上一行,增加 subpr ...

  9. rsync+inotify同步备份文件

    前言 rsync作用:man rsync可以看到解释为a fast, versatile, remote (and local) file-copying tool,主要进行文件的同步. inotif ...

  10. java----int,string 转化为long

    String: 1.返回Long包装类型: String str = "aaa"; long l = Long.parseLong([str]); 2.返回long基本数据类型: ...