@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的更多相关文章

  1. CF1494A ABC String 题解

    Content 给定 \(T\) 个仅包含大写字母 A,B,C 的字符串 \(s\).问你是否能够通过将每个 A,B,C 换成 (,) 中的一个(同一个字母必须要换成同一个字符),使得最后得到的括号序 ...

  2. 关于String str =new String("abc")和 String str = "abc"的比较

    String是一个非常常用的类,应该深入的去了解String 如: String str =new String("abc") String str1 = "abc&qu ...

  3. 经典String str = new String("abc")内存分配问题

    出自:http://blog.csdn.net/ycwload/article/details/2650059 今天要找和存储管理相关的一些知识,网上搜了半天也没有找到完善的(30%的程度都不到),没 ...

  4. java中String s="abc"及String s=new String("abc")详解

    1.   栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2.   栈的优势是,存取速度比堆要快,仅次于直 ...

  5. 面试题之String str = new String("abc"); 创建了几个对象

    今天去面试的时候碰到了这个问题:String str = new String("abc"); 创建了几个对象,回来自己研究并查阅资料才发现答错了..网上的争论不少,有的说是两个, ...

  6. java中String s = new String("abc")创建了几个对象?

    答案是两个,现在我们具体的说一下: String s = new String("abc");一.我们要明白两个概念,引用变量和对象,对象一般通过new在堆中创建,s只是一个引用变 ...

  7. String s=new String("abc")创建了几个对象?

    String str=new String("abc");   紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢? 答案应该是1个或者2个. 1个 ...

  8. 【转载】java 中 String s = new String("abc") 创建了几个对象?!

    原文链接点这里,感谢博主分享 答案是两个,现在我们具体的说一下: String s = new String("abc"); 首先我们要明白两个概念,引用变量和对象,对象一般通过n ...

  9. 关于String str =new String("abc")和 String str = "abc"的比较--转

    原文地址:https://www.cnblogs.com/OnlyCT/p/5433410.html String是一个非常常用的类,应该深入的去了解String 如: String str =new ...

随机推荐

  1. SSM11-solr服务的搭建

    1.  Solr服务搭建 1.1. Solr的环境 Solr是java开发. 需要安装jdk. 安装环境Linux. 需要安装Tomcat. 1.2. 搭建步骤 第一步:把solr 的压缩包上传到Li ...

  2. mac mamp host 配置

    <VirtualHost *:80> DocumentRoot "/Users/xuxu/www" ServerName localhost <Directory ...

  3. Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---状态模式[转]

    {没有应用状态模式的代码} //工程文件 program Project1; {$APPTYPE CONSOLE} uses  uGumballMachine in 'uGumballMachine. ...

  4. NOIP模拟赛 17.10.10

    初次见面(firstmeet)[题目背景]雾之湖边,静得可怕.露米娅出神凝望.黑白连衣裙,像极了绽放的墨黑和洁白的莲.身边的雾之湖,倒映着血色天空.酒红的双眸,映照一切.低声浅笑,双臂伸直,她悄无声息 ...

  5. 阿里云SaaS生态战略发布:成就亿级营收独角兽

    导语:本文中,阿里云智能资深技术专家黄省江从“势”“道”“术”三个方面分享了自己对于SaaS生态的理解,并介绍了SaaS加速器发布以来在产品.技术和商业侧最新的一些进展. 在321北京峰会上,阿里云公 ...

  6. 第十章—DOM(二)——Element类型

    Element类型用于表现HTML和XML,提供了对元素标签名,子节点和特效的访问.Element节点具有以下特征: 要访问元素的标签名,可以使用nodeName属性,也可以使用tagName属性.这 ...

  7. hasLayout是什么

    haslayout 是Windows Internet Explorer渲染引擎的一个内部组成部分.在InternetExplorer中,一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元 ...

  8. UML时序图(Sequence Diagram)学习笔记

    什么是时序图时序图(Sequence Diagram),又名序列图.循序图,是一种UML交互图.它通过描述对象之间发送消息的时间顺序显示多个对象之间的动态协作. 让我们来看一看visio2016对时序 ...

  9. redis是当前流行的nosql数据库

    redis是当前流行的nosql数据库,很多网站都用它来做缓存,今天我们来安装并配置下redis 二.安装并配置redis 1.安装redis sudo apt-get install redis-s ...

  10. Android LruCache源码简介

    package android.util; import java.util.LinkedHashMap; import java.util.Map; /** * A cache that holds ...