@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 ...
随机推荐
- angular1.0 $http jsonp callback
$http.jsonp(sDUrl,{cache:false,jsonpCallbackParam:'callback'}); https://stackoverflow.com/questions/ ...
- Laravel-admin之Driver [] is not supported
使用Laravel-admin做项目,原本好好的项目,今天一运行则报错:Driver [] is not supported,截图如下: 翻看百度翻译之后,才知道是不支持驱动器[],但是知道意思还是不 ...
- JAVA邀请码生成器
code import java.util.Random; /** * 邀请码生成器,算法原理:<br/> * 1) 获取id: 1127738 <br/> * 2) 使用自定 ...
- linux文件系统配置文件
文件系统 内核提供了一个接口,用来显示一些它的数据结构,这些数据结构对于决定诸如使用的中断.初始化的设备和内存统计信息之类的系统参数可能很有用.这个接口是作为一个独立但虚拟的文件系统提供的,称为 /p ...
- 快速乘O(1)和O(log)
O(1)快速乘来自骆可强:<论程序底层优化的一些方法与技巧> //O(1)快速乘 inline LL quick_mul(LL x,LL y,LL MOD){ x=x%MOD,y=y%MO ...
- 洛谷P2723 丑数 Humble Numbers [2017年 6月计划 数论07]
P2723 丑数 Humble Numbers 题目背景 对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S.这个正整数集合包括, ...
- 洛谷3953 (NOIp2017) 逛公园——记忆化搜索+用栈判0环
题目:https://www.luogu.org/problemnew/show/P3953 因为K只有50,所以想到用dp[ cr ][ j ]表示在点cr.比最短路多走了 j 的方案数.(看了TJ ...
- Faster RCNN算法demo代码解析
一. Faster-RCNN代码解释 先看看代码结构: Data: This directory holds (after you download them): Caffe models pre-t ...
- 微信小程序--每个独立的page的page.json只能修改window属性
app.json 配置项列表 app.json文件用来对微信小程序进行全局配置,决定页面文件的路径.窗口表现.设置网络超时时间.设置多 tab 等. window配置 用于设置小程序的状态栏.导航条. ...
- Session学习小结
前言: 1.我们在学习一项技术的时候,首先应该是什么时候会用到这项技术.这次学习session也是如此,一般的web项目中都有用户的存在,有用户那么就有了用户的管理,而用户往往是存在于session中 ...