测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A40201. 游园安排

填空题 困难

题目描述

游园安排

题目描述

L 星球游乐园非常有趣,吸引着各个星球的游客前来游玩。

小蓝是 L 星球游乐园的管理员,为了更好的管理游乐园,游乐园要求所有的游客提前预约,小蓝能看到系统上所有预约游客的名字。

每个游客的名字由一个大写英文字母开始,后面跟 0 00 个或多个小写英文字母,游客可能重名。

小蓝特别喜欢递增的事物。今天,他决定在所有预约的游客中,选择一部分游客在上午游玩,其他的游客都在下午游玩,

在上午游玩的游客要求按照预约的顺序排列后,名字是单调递增的,即排在前面的名字严格小于排在后面的名字。

一个名字 A AA 小于另一个名字 B BB 是指:

存在一个整数 i ii,使得 A AA 的前 i ii 个字母与 B BB 的前 i ii 个字母相同,且 A AA 的第 i + 1 i+1i+1 个字母小于 B BB 的第 i + 1 i+1i+1 个字母

如果 A AA 不存在第 i + 1 i + 1i+1 个字母且 B BB 存在第 i + 1 i + 1i+1 个字母,也视为 A AA 的第 i + 1 i + 1i+1 个字母小于 B BB 的第 i + 1 i + 1i+1 个字母


作为小蓝的助手,你要按照小蓝的想法安排游客,同时你又希望上午有尽量多的游客游玩,请告诉小蓝让哪些游客上午游玩。

如果方案有多种,请输出上午游玩的第一个游客名字最小的方案。

如果此时还有多种方案,请输出第一个游客名字最小的前提下第二个游客名字最小的方案。

如果仍然有多种,依此类推选择第三个、第四个……游客名字最小的方案。

输入格式

输入包含一个字符串,按预约的顺序给出所有游客的名字,相邻的游客名字之间没有字符分隔。

输出格式

按预约顺序输出上午游玩的游客名单,中间不加任何分隔字符。

样例输入

WoAiLanQiaoBei

样例输出

AiLanQiao

数据范围

对于 20% 的评测数据,输入的总长度不超过 20 2020 个字母。

对于 50% 的评测数据,输入的总长度不超过 300 300300 个字母。

对于 70% 的评测数据,输入的总长度不超过 10000 1000010000 个字母。

对于所有评测数据,每个名字的长度不超过 10 1010 个字母,输入的总长度不超过 1000000 10000001000000 个字母。

参考答案

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 1e9; const int maxn = 1e4; string s, anss; string ss[maxn]; int dp[maxn]; //dp[i]表示 以第i个【字符串】结尾的 最长递增子序列长度 string v[maxn]; //v[i]记录对应dp[i]的字符串方案 int cnt, ansl; bool less_than(string s1, string s2){ int i = 0, j = 0; while(s1[i] == s2[j]){ i++; j++; } if(s1[i] >= 'a' && s2[j] >= 'a' || s1[i] < 'a' && s2[j] < 'a'){ return s1[i] < s2[j]; }else{// 一个大写一个小写 return s1[i] < 'a'; //如果s1[i]大写,说明上一个名字s1是s2的前缀,故s1一定小于s2; } } int main(){ cin >> s; //字符串拆分 for(int i = 0; i < s.size(); ){ int j = i + 1; if(s[i] < 'a'){ //大写首字母 while(s[j] >= 'a'){ j++; } } string tmp = s.substr(i, j - i); ss[cnt++] = tmp; i = j; } //dp初始化 for(int i = 0; i < cnt; i++){ dp[i] = 1; v[i] = ss[i]; } //状态转移 for(int i = 1; i < cnt; i++){ for(int j = 0; j < i; j++){ if(ss[j] < ss[i]){ if(dp[j] + 1 > dp[i]){ dp[i] = dp[j] + 1; v[i] = v[j] + ss[i]; if(dp[i] > ansl){ ansl = dp[i]; anss = v[i]; } } else if(dp[j] + 1 == dp[i]){ //同等长度 if(less_than(v[j] + ss[i], v[i])){ v[i] = v[j] + ss[i]; //更新v[i] } if(dp[i] == ansl){ anss = v[i]; } } } } } cout << anss; return 0; }
上一题 下一题