@atcoder - AGC036E@ ABC String
@description@
给定一个仅由 A, B, C 组成的字符串 S。
求 S 的一个最长子序列(不一定连续),满足:
(1)A, B, C 出现了相同次数。
(2)子序列中相邻字符不相同。
输出该子序列。
Constraints
1≤|S|≤10^6
S 仅由 A, B, C 组成。
Input
输入仅给定单个字符串 S。
Output
输出任意一个满足条件的最长子序列。
Sample Input 1
ABBCBCAB
Sample Output 1
ACBCAB
Sample Input 2
ABABABABACACACAC
Sample Output 2
BABCAC
@solution@
不难想到,在原串 S 中相同的相邻字符可以先取掉,即一个去重操作。
不妨假设 cntA <= cntB <= cntC,即 A 的数量是最少的。
因为我们的最长子序列最大也只能到 3*cntA,而且可能会更少。
我们希望删尽量少的 A,来使得三者相同。
用字符 A 将原序列分割成若干段,每一段肯定是 BCBCB... 这样 B, C 交替出现。
我们先想办法让 cntB = cntC。假如一个 C 的两边不相同,去掉它过后不会影响结果,我们就直接删掉它。
如果还是 cntB < cntC,此时每一段要么是 ABCB...CBA,这种类型 B 只能比 C 多 1 个,不可再更改;要么是 ACA,即两个 A 中间夹一个 C,我们可以同时去掉一个 A 与一个 C。
可以发现这些 A 是必须去掉的,不然 cntB 永远无法等于 cntC。
现在就有 cntA <= cntB = cntC,我们来想办法让 cntA = cntB = cntC。
可以每次删一个 "BC" 或者 "CB" 模样的子串,但是必须要保证删完过后两个 A 不会靠在一起。
最后如果还有 A,则至少都有 ABCACBA...BCA,即两个 A 中间夹一个 "BC" 或 "CB"。这时 cntA > cntB = cntC。
所以删的过程一定存在每一刻满足题意。
注意如果最终三个字符的数量依然不相等,就无解。
删除什么的可以用链表 O(1) 搞。总复杂度 O(n)。
@accepted code@
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1000000;
int cnt[3], b[3], c[3];
void get() {
if( cnt[0] >= cnt[1] && cnt[1] >= cnt[2] )
c[b[0] = 2] = 0, c[b[1] = 1] = 1, c[b[2] = 0] = 2;
else if( cnt[0] >= cnt[2] && cnt[2] >= cnt[1] )
c[b[0] = 2] = 0, c[b[2] = 1] = 2, c[b[1] = 0] = 1;
else if( cnt[1] >= cnt[0] && cnt[0] >= cnt[2] )
c[b[1] = 2] = 1, c[b[0] = 1] = 0, c[b[2] = 0] = 2;
else if( cnt[1] >= cnt[2] && cnt[2] >= cnt[0] )
c[b[1] = 2] = 1, c[b[2] = 1] = 2, c[b[0] = 0] = 0;
else if( cnt[2] >= cnt[0] && cnt[0] >= cnt[1] )
c[b[2] = 2] = 2, c[b[0] = 1] = 0, c[b[1] = 0] = 1;
else if( cnt[2] >= cnt[1] && cnt[1] >= cnt[0] )
c[b[2] = 2] = 2, c[b[1] = 1] = 1, c[b[0] = 0] = 0;
}
int lst[MAXN + 5], nxt[MAXN + 5];
int a[MAXN + 5], n;
void erase(int x) {
lst[nxt[x]] = lst[x], nxt[lst[x]] = nxt[x];
cnt[a[x]]--;
}
char s[MAXN + 5];
vector<int>v;
int main() {
scanf("%s", s + 1), n = strlen(s + 1);
for(int i=0;i<=n+1;i++)
lst[i] = i - 1, nxt[i] = i + 1;
a[0] = a[n + 1] = -1;
for(int i=1;i<=n;i++) {
cnt[a[i] = s[i] - 'A']++;
if( a[i] == a[i-1] ) erase(i);
}
get();
for(int i=nxt[0];i!=n+1;i=nxt[i])
if( a[i] == c[2] && a[lst[i]] != a[nxt[i]] )
v.push_back(i);
for(int i=0;i<v.size()&&cnt[c[2]]!=cnt[c[1]];i++)
erase(v[i]);
v.clear();
for(int i=nxt[0];i!=n+1;i=nxt[i])
if( a[i] == c[2] && a[lst[i]] == c[0] && a[nxt[i]] == c[0] )
v.push_back(i);
for(int i=0;i<v.size()&&cnt[c[2]]!=cnt[c[1]];i++)
erase(v[i]), erase(nxt[v[i]]);
v.clear();
for(int i=nxt[0];i!=n+1;i=nxt[i])
if( a[i] == c[2] && a[nxt[i]] == c[1] )
v.push_back(i);
for(int i=0;i<v.size()&&cnt[c[0]]!=cnt[c[1]];i++)
if( a[lst[v[i]]] != c[0] || a[nxt[nxt[v[i]]]] != c[0] )
erase(v[i]), erase(nxt[v[i]]);
v.clear();
for(int i=nxt[0];i!=n+1;i=nxt[i])
if( a[i] == c[2] && a[lst[i]] == c[1] )
v.push_back(i);
for(int i=0;i<v.size()&&cnt[c[0]]!=cnt[c[1]];i++)
if( a[nxt[v[i]]] != c[0] || a[lst[lst[v[i]]]] != c[0] )
erase(v[i]), erase(lst[v[i]]);
v.clear();
if( cnt[0] == cnt[1] && cnt[0] == cnt[2] ) {
for(int i=nxt[0];i!=n+1;i=nxt[i])
putchar(a[i] + 'A');
}
}
@details@
这个肯定比 AGC036D 好想。
注意有些字符删掉是会互相影响的。有可能前一个删掉,后一个原本可以删,又变成不能删的了。
@atcoder - AGC036E@ ABC String的更多相关文章
- CF1494A ABC String 题解
Content 给定 \(T\) 个仅包含大写字母 A,B,C 的字符串 \(s\).问你是否能够通过将每个 A,B,C 换成 (,) 中的一个(同一个字母必须要换成同一个字符),使得最后得到的括号序 ...
- 关于String str =new String("abc")和 String str = "abc"的比较
String是一个非常常用的类,应该深入的去了解String 如: String str =new String("abc") String str1 = "abc&qu ...
- 经典String str = new String("abc")内存分配问题
出自:http://blog.csdn.net/ycwload/article/details/2650059 今天要找和存储管理相关的一些知识,网上搜了半天也没有找到完善的(30%的程度都不到),没 ...
- java中String s="abc"及String s=new String("abc")详解
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度比堆要快,仅次于直 ...
- 面试题之String str = new String("abc"); 创建了几个对象
今天去面试的时候碰到了这个问题:String str = new String("abc"); 创建了几个对象,回来自己研究并查阅资料才发现答错了..网上的争论不少,有的说是两个, ...
- java中String s = new String("abc")创建了几个对象?
答案是两个,现在我们具体的说一下: String s = new String("abc");一.我们要明白两个概念,引用变量和对象,对象一般通过new在堆中创建,s只是一个引用变 ...
- String s=new String("abc")创建了几个对象?
String str=new String("abc"); 紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢? 答案应该是1个或者2个. 1个 ...
- 【转载】java 中 String s = new String("abc") 创建了几个对象?!
原文链接点这里,感谢博主分享 答案是两个,现在我们具体的说一下: String s = new String("abc"); 首先我们要明白两个概念,引用变量和对象,对象一般通过n ...
- 关于String str =new String("abc")和 String str = "abc"的比较--转
原文地址:https://www.cnblogs.com/OnlyCT/p/5433410.html String是一个非常常用的类,应该深入的去了解String 如: String str =new ...
随机推荐
- CodeChef--EQUAKE
题目链接 Earthquake in Bytetown! Situation is getting out of control! All buildings in Bytetown stand on ...
- 磁力搜索网站 BT torrent search engine 推荐 2019/12/25日更新
btkitty 知名的BT磁力搜索,资源很多,中文友好 btdb 知名的BT磁力搜索,资源很多,中文友好 838888 不错的 BT 磁力搜索引擎,资源很多,中文友好 idope.se 资源丰富的BT ...
- char类型和int类型之间的转换
在视屏课程第二章里,我们已经学习了一些常用的数据类型转换.然而,有一些时候我们会经常会遇到将char类型转换成int类型,或者需要将int类型转换为char类型的情况. 这里,我们来探讨一下这种不常用 ...
- springmvc 使用了登录拦截器之后静态资源还是会被拦截的处理办法
解决办法 在拦截器的配置里加上静态资源的处理 参考https://www.jb51.net/article/103704.htm
- Python爬虫之selenium库使用详解
Python爬虫之selenium库使用详解 本章内容如下: 什么是Selenium selenium基本使用 声明浏览器对象 访问页面 查找元素 多个元素查找 元素交互操作 交互动作 执行JavaS ...
- 火狐下button标签子元素无法点击
button下元素点击事件:在chrome和safari下每个a标签可以点击,在火狐下a标签无法点击. <button> <a href="javascript:;&quo ...
- 2016年中国独角兽企业估值榜 TOP300
2016年中国独角兽企业估值榜 TOP300[完整榜单] 类型:品牌资讯/名企动态 阅读:6735次 来源: 中商情报网 我要评论 摘要:独角兽公司是什么?独角兽公司指的是那些估值达到10亿美元以 ...
- ecshop二次开发之电子票
前台效果展示: 2. 3. 后台展示效果: 代码实现: 一. 添加菜单项:路径admin\includes\inc_menu.PHP $modules['18_ticket_m ...
- GDSOI2017第三轮模拟4.21 总结
1 第一题看着就觉得猎奇,于是就想着打暴力就跑. 但是很严重的问题就是... \(D\)和\(B\)打反了,都不知道当时在干什么??? 原本可以拿35. 2 第二题看着就觉得套路,于是想着今天就攻这题 ...
- PYTHON网络爬虫与信息提取[正则表达式的使用](单元七)
正则表达式由字符和操作符构成 . 表示任何单个字符 []字符集,对单个字符给出取值范围 [abc]或者关系 [a-z]表示 [^abc]表示非这里面的东西 非字符集 * 表示星号之前的字符出现0次或 ...