@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 ...
随机推荐
- Spring相关技术记录
@ResponseStatus(value=) Hibernate OneToOne: 使用optional=false,才能使用lazy 如果关联字段是当前表的主键,我试了不加optional=fa ...
- JavaScript中this的指向2(转载)
1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法. 2. 相同点:这两个方法的作用是一样的. 都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖 ...
- C# 多线程的代价~内存都被吃了!
异步操作是.net4.5推出的新名词,事实上,这东西早就有了,它归根结底是通过线程池来实现的,即将一个大任务分成多个小任何块,每个线程并行处理其中的一个,完成后再把结果告诉主线程,在.net4.5推出 ...
- Centos系统Python环境搭建和项目部署
目录 一.Python 1. 源安装 Python3 2. SCL安装 Python3 3. 虚拟环境venv 4. 安装Flask 5. 安装gunicorn 二.安装Nginx 1. 安装Ngin ...
- 【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 ...
- js this工作原理
js中的this是个很妙的东西,你经常不知道它到底在指向谁,又是谁在调用它. 通用判断方法: 1.this总是指向它的直接调用者 var a={ user:'Artimis', fn:function ...
- 数据库---JDBC的解析
一.JDBC是什么? JDBC:Java Database Connectivity(Java数据库连接池).指定了统一的访问各种关系型数据库的标准接口-----桥梁作用. 功能:[与数据库建立连接 ...
- Springboot 创建的maven获取resource资源下的文件的两种方式
Springboot 创建的maven项目 打包后获取resource下的资源文件的两种方式: 资源目录: resources/config/wordFileXml/wordFileRecord.xm ...
- const、引用与指针
前提 我们忽略掉了相同类型是否可以赋值的情况(我到现在的学习里都还可以相互赋值),以及类型兼容的情况.只考虑const.&.*等修饰符带来的影响 类型兼容: 强制类型转换 基类与子类间的兼容 ...
- IDEA maven项目查自动查看依赖关系,解决包冲突问题
在maven项目中找到pom.xml,打开. <dependencies> <dependency> <groupId>org.apache.storm</g ...