@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. Spring相关技术记录

    @ResponseStatus(value=) Hibernate OneToOne: 使用optional=false,才能使用lazy 如果关联字段是当前表的主键,我试了不加optional=fa ...

  2. JavaScript中this的指向2(转载)

    1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法. 2. 相同点:这两个方法的作用是一样的. 都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖 ...

  3. C# 多线程的代价~内存都被吃了!

    异步操作是.net4.5推出的新名词,事实上,这东西早就有了,它归根结底是通过线程池来实现的,即将一个大任务分成多个小任何块,每个线程并行处理其中的一个,完成后再把结果告诉主线程,在.net4.5推出 ...

  4. Centos系统Python环境搭建和项目部署

    目录 一.Python 1. 源安装 Python3 2. SCL安装 Python3 3. 虚拟环境venv 4. 安装Flask 5. 安装gunicorn 二.安装Nginx 1. 安装Ngin ...

  5. 【eclipse】解决:eclipse或STS运行maven工程出现Missing artifact jdk.tools:jdk.tools:jar:1.7问题

    eclipse或STS运行maven工程出现Missing artifact jdk.tools:jdk.tools:jar:1.7问题 最近项目中使用到大数据平台,代码中应用了hbase-clien ...

  6. js this工作原理

    js中的this是个很妙的东西,你经常不知道它到底在指向谁,又是谁在调用它. 通用判断方法: 1.this总是指向它的直接调用者 var a={ user:'Artimis', fn:function ...

  7. 数据库---JDBC的解析

    一.JDBC是什么? JDBC:Java Database Connectivity(Java数据库连接池).指定了统一的访问各种关系型数据库的标准接口-----桥梁作用.  功能:[与数据库建立连接 ...

  8. Springboot 创建的maven获取resource资源下的文件的两种方式

    Springboot 创建的maven项目 打包后获取resource下的资源文件的两种方式: 资源目录: resources/config/wordFileXml/wordFileRecord.xm ...

  9. const、引用与指针

    前提 我们忽略掉了相同类型是否可以赋值的情况(我到现在的学习里都还可以相互赋值),以及类型兼容的情况.只考虑const.&.*等修饰符带来的影响 类型兼容: 强制类型转换 基类与子类间的兼容 ...

  10. IDEA maven项目查自动查看依赖关系,解决包冲突问题

    在maven项目中找到pom.xml,打开. <dependencies> <dependency> <groupId>org.apache.storm</g ...