\(\texttt{Problem Link}\)

简要题意

在一个字符串 \(s\) 中,对于每个后缀,任意删掉一些相邻的相同的字符,使得字符串字典序最小。

注意:删掉之后拼起来再出现的相邻相同字符不能够删除。

思路

倍增好题

发现存在局部最优解(最优子结构),并且可以转移到其它结点,可以考虑使用 dp

那就设 \(f _ i\) 表示 \([i , n]\) 经过一些操作,达成的字典序最小的字符串(求后缀最优解,从后往前遍历)。

可以得到状态转移:

\[
f_i =

\begin{cases}

f_{i+1} + s_i, & s_i \neq s_{i+1},\\

\min \{f_{i+1} + s_i , f_{i+2}\} & s_i = s_{i+1}. \\
\end{cases}
\]

\(s_i\) 表示第 \(i\) 个字符,\(\min\) 表示字典序更小的那个。

边界条件:\(f_n = s_n\)。

但是这样做的复杂度是 \(\mathcal{O}(n^2)\)。

字典序比较优化

瓶颈在于比较字典序。

考虑对字典序比较进行优化。

回顾字典序比较的过程,

过程是对于两个字符串,从头到尾一个个字符进行比较,遇到第一个字符不同时,就返回答案。

那么就可以有一个想法通过一些操作,快速找到第一个不同的字符。

可以考虑使用倍增优化,把两个串比较时,通过倍增找到 hash 值第一个不同的地方,这样字符串比较就能优化到 \(\mathcal{O}(\log n)\)。

输出优化

接下来的问题就是输出,

因为输出长字符只要输出前 \(5\) 个和最后 \(2\) 个。

所以可以对于前面的字符直接输出,后面的字符也可以写个倍增往后跳到需要的。

最后总的复杂度就是 \(\mathcal{O}(n \log n)\)。

Code

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm> using i64 = long long ;
using ui64 = unsigned long long ; const int N = 1e5 + 5 ;
const int base = 131 ; char s[N];
int f[N] , g[N] , h[N];
ui64 Pow[100];
ui64 Hash[20][N];//自然溢出
int nxt[20][N];
int n; void updata(int u, int v){
v = h[v];
h[u] = u;
g[u] = g[v] + 1;//记录当前的长度
nxt[0][u] = v;
Hash[0][u] = s[u] - 'a'; for(int i = 1; i <= 19; i++)
nxt[i][u] = nxt[i-1][nxt[i-1][u]] , Hash[i][u] = Hash[i-1][u] * Pow[i - 1] + Hash[i-1][nxt[i-1][u]]; //处理hash倍增
// nxt是方便向后跳2^k的
} int min(int x, int y){
int tx = x , ty = y; x = h[x] , y = h[y]; for(int i = 19; i >= 0; i--)
if(nxt[i][x] && nxt[i][y] && Hash[i][x] == Hash[i][y])
x = nxt[i][x] , y = nxt[i][y];//找到第一个不同的字符 return Hash[0][x] < Hash[0][y]? tx: ty;//小细节不能写 <= 写 <= 会导致部分少删除
} int main(){ scanf("%s",s+1); n = strlen(s+1); Pow[0] = base;
for(int i = 1; i <= 90; i++)
Pow[i] = Pow[i - 1] * Pow[i - 1];//预处理 base 的 2^i 次方,方便将hash值拼起来 for(int i = n; i >= 1; i--) {
updata(i,i+1);//默认是接上字符 if(i < n && s[i] == s[i+1] && min(i,i + 2) == i + 2) {//删除更优
h[i] = h[h[i + 2]];
g[i] = g[h[i + 2]];
}
} for(int i = 1; i <= n; i++) {
printf("%d ",g[i]); int id = h[i];
if(g[i] <= 10) {
for(int j = id; j && j <= n; j = nxt[0][j])
putchar(s[j]);
} else {
for(int j = 1; j <= 5; j++ , id = nxt[0][id])//前5个字符直接暴力找
putchar(s[id]); printf("..."); id = h[i];
int len = g[i] - 2 ; for(int i = 19; i >= 0; i--)
if(nxt[i][id] && (1<<i) <= len) len -= 1<<i , id = nxt[i][id];//倍增找最后两个字符 for(int j = 1; j <= 2; j++ , id = nxt[0][id])
putchar(s[id]);
} puts("");
}
return 0;
}

牢骚

本来思路是完全正确的,但是我用了一个 Trie 树和递归找字符串,导致常数太大,真的气死人了。

Minlexes题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. 「源码分析」CopyOnWriteArrayList 中的隐藏的知识,你Get了吗?

    点赞再看,动力无限.Hello world : ) 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. 前言 ...

  2. VS2019 添加三方文件夹遇到的坑

    在开发新项目时需要用到一些三方 API,这些三方 API 没有生成 lib,所以我们在 VS 编译器中添加这些三方文件夹的头文件路径后 会出现 ERROR LNK2019 的错误提示,这些提示通常都是 ...

  3. 文心一言 VS 讯飞星火 VS chatgpt (201)-- 算法导论15.2 6题

    六.用go语言,证明:对 n 个元素的表达式进行完全括号化,恰好需要 n-1 对括号. 文心一言,代码正常运行: 在Go语言中,证明对n个元素的表达式进行完全括号化恰好需要n-1对括号,可以通过数学归 ...

  4. .net core6 Autofac依赖注入

    一.引言 .net core6在文件方面是精简了,所以配置方面也发生了部分变化:下面记录下.net core6中怎么配置Autofac 进行依赖注入. 二.项目创建 1).首先引用两个包:在Nuget ...

  5. Flask遇到的坑及解决办法

    flask_script 在使用第三方包flask_script时,报一下错误 ModuleNotFoundError: No module named 'flask._compat' 问题时flas ...

  6. 【Azure 环境】向Azure Key Vault中导入证书有输入密码,那么导出pfx证书的时候,为什么没有密码呢?

    问题描述 将pfx证书导入Key Vault的证书时,这个PFX需要输入正确的密码导入成功.但是当需要导出时,生成的pfx证书则不需要密码.这是正常的情况吗? 问题解答 是的,这是Azure Key ...

  7. 【Azure Developer】AAD API如何获取用户“Block sign in”信息(accountEnabled)

    问题描述 使用API获取所有Azure AD中的用户列表,API所参考的文档:https://docs.microsoft.com/en-us/graph/api/user-list?view=gra ...

  8. 【Azure 媒体服务】在Azure Media Service门户中使用HLS模式传输视频流,播放视频步骤

    问题描述 如何在Azure Media Service门户中使用HLS模式传输视频流,播放视频步骤 问题解决 第一步:在 Media Service 这边点击资产.上传本地视频资源作为Media Se ...

  9. 【XInput】手柄模拟鼠标运作之 .NET P/Invoke 和 UWP-API 方案

    上一篇中,老周简单肤浅地介绍了 XInput API 的使用,并模拟了鼠标移动,左.右键单击和滚轮.本篇,咱们用 .NET 代码来完成相同的效果. 说起来也是倒霉,博文写了一半,电脑忽然断电了.不知道 ...

  10. Java 多态 案列

    1 package com.bytezreo.duotai; 2 3 //多态性的使用 举例一 4 public class AnimalTest 5 { 6 public static void m ...