题面

ARC058D Iroha Loves Strings

给定 \(n\) 个字符串,从中选出若干个按给出顺序连接起来,总长等于 \(m\),求字典序最小的,保证有解。

数据范围:\(1\le n\le 2000\),\(1\le k\le 10^4\),字符串总长 \(S\le 10^6\)。


题解

atcoder 的题就是好啊,非常巧妙,毫不毒瘤。

这篇题解要抨击 Z-functionycx,造福人民。

有一个非常显然的思路:每次选当前选了的串右边没选且能选的中最小的。

这里的能选的可以用个后缀背包判断,可以用 bitset 维护。

注意到对于每个长度 \(i\) 能不能由后缀拼成有个分界点,设为 \(r_i\)。

这个做法有个明显的问题:如果有一个串 geo 和一个串 geoafo,怎么知道哪个好呢?

如果选了 geo,如果剩下的串只有 boomzero,那么就不如 geoafo 了。

如果选了 geoafo,如果剩下的串有个 aba,那么就 geoaba 更优了。

所以想到用 dp,来避免不同长度的字符串的比较。

设 \(f_i\) 表示拼成的长度为 \(i\) 且剩下字符串可以拼成 \(m-i\) 的字符串中字典序最小的(注意 \(f_i\) 是个字符串!)。

然后 \(g_i\) 是拼成 \(f_i\) 的最右字符串的编号,要最左。

转移就是从小到大枚举每个 \(i\)(前提是有这样的 \(f_i\)),然后枚举加上的字符串长度 \(j\)。

要找到 \(g_i\) 到 \(r_{m-i-j}\) 中长度为 \(j\) 的字典序最小字符串,这个可以用 st 表预处理 \(\Theta(1)\) 完成。

然后把这个串加到 \(f_i\) 后面暴力和 \(f_{i+j}\) 比较即可。

关于时间复杂度,总感觉是 \(\Theta(n^2)\) 的,但是不会证,就当 \(\Theta(n^3)\) 的吧(可是它明明跑得很快 /kk)。


代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f; //Data
const int N=2000+1,M=1e4+1,D=12;
int n,m,o[N],we[N],ri[M],g[M];
vector<int> id[M],st[M][D];
string s[N],f[M];
bitset<M> h[N]; //Functions
int get(int j,int l,int r){
l=lower_bound(id[j].bg,id[j].ed,l)-id[j].bg;
r=lower_bound(id[j].bg,id[j].ed,r)-id[j].bg;
if(r-l<=0) return -1;
int t=log2(r-l),&a=st[j][t][l],&b=st[j][t][r-(1<<t)];
return we[a]>we[b]?b:a;
} //Main
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m,h[n].set(0);
R(i,n) cin>>s[o[i]=i];
stable_sort(o,o+n,[&](int i,int j){return s[i]<s[j];});
R(i,n) we[o[i]]=i,id[sz(s[i])].pb(i);
R(i,m+1){
g[i]=-1,ri[i]=0;
vector<int> &c=id[i],*a=st[i];
if(!sz(c)) continue;
R(i,D) a[i].resize(sz(c));
R(i,sz(c)) a[0][i]=c[i];
R(t,D-1)R(i,sz(c)+1-(2<<t)){
int &x=a[t][i],&y=a[t][i+(1<<t)];
a[t+1][i]=we[x]>we[y]?y:x;
}
}
L(i,n){
h[i]=h[i+1]|h[i+1]<<sz(s[i]);
R(j,m+1)if(h[i][j]&&!h[i+1][j]) ri[j]=i;
}
f[0]="",g[0]=0,ri[0]=n;
R(j,m)if(~g[j])L(i,m+1-j){
int t=get(i,g[j],ri[m-j-i]);
// cout<<"j="<<j<<"->j+i="<<j+i<<'\n';
// cout<<"get("<<i<<","<<g[j]<<","<<ri[m-j-i]<<")="<<t<<'\n';
if(~t&&(!~g[j+i]||f[j+i]>f[j]+s[t]))
f[j+i]=f[j]+s[t],g[j+i]=t+1;
}
// R(i,m+1) cout<<g[i]<<" "<<f[i]<<'\n';
cout<<f[m]<<'\n';
return 0;
}

祝大家学习愉快!

题解-ARC058D Iroha Loves Strings的更多相关文章

  1. 文字列大好きいろはちゃんイージー / Iroha Loves Strings (ABC Edition) (优先队列)

    题目链接:http://abc042.contest.atcoder.jp/tasks/abc042_b Time limit : 2sec / Memory limit : 256MB Score ...

  2. Atcoder Regular Contest 058 D - 文字列大好きいろはちゃん / Iroha Loves Strings(单调栈+Z 函数)

    洛谷题面传送门 & Atcoder 题面传送门 神仙题. mol 一发现场(bushi)独立切掉此题的 ycx %%%%%%% 首先咱们可以想到一个非常 naive 的 DP,\(dp_{i, ...

  3. Codeforces Round #254 (Div. 1) D - DZY Loves Strings

    D - DZY Loves Strings 思路:感觉这种把询问按大小分成两类解决的问题都很不好想.. https://codeforces.com/blog/entry/12959 题解说得很清楚啦 ...

  4. Codeforces Round #254 (Div. 1) D. DZY Loves Strings hash 暴力

    D. DZY Loves Strings 题目连接: http://codeforces.com/contest/444/problem/D Description DZY loves strings ...

  5. [CodeForces - 447B] B - DZY Loves Strings

    B - DZY Loves Strings DZY loves collecting special strings which only contain lowercase letters. For ...

  6. 【题解】DZY Loves Chinese

    [题解]DZY Loves Chinese II 不吐槽这题面了... 考虑如何维护图的连通性,如果把图的变成一颗的\(dfs\)生成树,那么如果把一个节点的父边和他接下来所有的返祖边删除,那么我们就 ...

  7. Codeforces Round #FF (Div. 2):B. DZY Loves Strings

    B. DZY Loves Strings time limit per test 1 second memory limit per test 256 megabytes input standard ...

  8. CF447B DZY Loves Strings 题解

    Content 有一个长度为 \(n\) 的仅含小写字母的字符串 \(s\) 以及 26 个英文小写字母的价值 \(W_\texttt{a},W_\texttt{b},...,W_\texttt{z} ...

  9. CF447B DZY Loves Strings 贪心

    DZY loves collecting special strings which only contain lowercase letters. For each lowercase letter ...

随机推荐

  1. dpdk网卡收包分析

    一个网络报文从网卡接收到被应用处理,中间主要需要经历两个阶段: 阶段一:网卡通过其DMA硬件将收到的报文写入到收包队列中(入队)阶段二:应用从收包队列中读取报文(出队)由于目前正在使用vpp/dpdk ...

  2. pandas.DataFarme内置的绘图功能参数说明

    可视化是数据探索性分析及结果表达的一种非常重要的形式,因此打算写一个python绘图系列,本文是第一篇,先说一下pandas.DataFrame.plot()绘图功能. pandas.DataFram ...

  3. JS之DOM(一)

    一.DOM简介 什么是DOM?简单地说,DOM是是针对HTML和XML文档的一个API,一套对文档的内容进行抽象和概念化的方法. 学习过ORM的同学可能知道ORM是将数据库中的表映射到类,建立一个表和 ...

  4. linux域名解析引起登陆慢

    linux域名解析引起登陆慢的问题在于,ssh去登录这个台机器的时候,本机会去通过域名解析获取登录主机的主机名,所有一旦域名解析是无效的,需要等待较长时间 解决办法一: 将域名解析指到127.0.0. ...

  5. CSS opacity设置不透明度

    1.opacity设置不透明度 opacity会将含有这个属性的子类都变成具有opacity属性,可以改变元素.元素内容.字标签的不透明度.而rgba只会改变设置的那个背景颜色的透明度效果 <! ...

  6. Java(7)泛型

    目录 一.泛型概述 1.什么是泛型 2.为什么用泛型 3.在集合中使用泛型 二.自定义泛型结构 1.泛型类.接口 2.泛型方法 三.举例泛型类和泛型方法的使用场景 1.泛型类举例: 2.泛型方法举例 ...

  7. Linux安装部署Redis(超级详细)

    前言 网上搜索了一筐如何在Linux下安装部署Redis的文章,各种文章混搭在一起勉强安装成功了.自己也记录下,方便后续安装时候有个借鉴之处. Redis版本 5.0.4 服务器版本 Linux Ce ...

  8. 直面秋招!非科班生背水一战,最终拿下阿里等大厂offer!

    前言 2020年已经接近到9月份了,很多粉丝朋友都对金九银十雀雀欲试了吧!也有很多朋友向我求教经验,因为我自己工作相对于稳定,在这里给大家分享一个粉丝朋友的经历,他作为一个曾经的菜鸡面试者,在不断的失 ...

  9. MindManager使用教程:如何导出HTML5交互式导图

    Mindmanager思维导图软件有着友好的用户界面以及丰富的思维导图制作功能.再搭配与Microsoft 软件的无缝集成功能,使得这款思维导图软件越来越受到职场人士的喜爱. 不仅是作为制作思维导图的 ...

  10. MarkDown学习总结-2020.05.11

    1.使用工具 1.1Typora 官网地址:https://www.typora.io/ 下载链接 2.基础入门 注意: []中的内容则是对应格式的标记符,默认全部标识符后面需要多加一个空格才能生效. ...