1 条题解
-
0
📝 题目大意
给定一个由
A、B、C组成、长度为 的字符串 。你可以进行两种操作:将A替换为BB,或将相邻的BB替换为A。求所有可达字符串中字典序最小的一个。💡 解题思路
-
题目分析:
- ,需要 或 的算法。
- 操作
A ↔ BB是可逆的,说明A和BB在某种意义下等价。 C不参与任何操作,是固定的"墙壁",将字符串分割为若干独立段。
-
算法推导:
- 将
A视为 2 个"B 单位",B视为 1 个"B 单位"。两种操作均不改变 B 单位总数。 - 可以证明:在相邻位置,
BA可以变为AB(),即A和B可以自由交换。 - 因此,在相邻
C之间的每一段中,我们可以任意排列A和B,且可以任意进行A ↔ BB的转换。唯一不变量是该段的 B 单位总数。 - 要使字典序最小,应尽量把
A放在前面:设某段 B 单位总数为 ,则最优排列为 个A后跟 个B(即A尽可能多,至多剩余一个B)。 - std.cpp 中的贪心实现:从左到右扫描,遇到
B时:- 若下一个字符是
A,则交换二者(BA → AB),将A向左推,使字典序更小; - 若下一个字符是
B,则合并为A(BB → A),并跳过被合并的B(++i)。 遇到A或C直接输出。单次扫描即可将字符串变为最优形式。
- 若下一个字符是
- 将
-
边界与细节:
- 当
i = N-1时,s[i+1]访问到字符串末尾的\0,不会等于'A'或'B',因此不会触发任何操作,安全。 BB → A时++i会跳过下一个字符,配合for循环自身的i++,实际一次跳过两个位置,保证输出长度正确。- 注意
C的分隔作用:C前后的A/B不能跨越C进行交换或合并。
- 当
⏱️ 复杂度分析
- 时间复杂度:,仅需一次从左到右的线性扫描。
- 空间复杂度:,存储输入字符串(可优化为 流式处理,但 std.cpp 使用 )。
💻 标准代码 (C++)
#include<bits/stdc++.h> using namespace std; int n;string s; int main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); cin>>n>>s; for(int i=0;i<n;i++) { if(s[i]=='B') { // BA → AB:将 A 向左推,使字典序更小 if(s[i+1]=='A')swap(s[i],s[i+1]); // BB → A:合并两个 B 为一个 A,并跳过下一个字符 else if(s[i+1]=='B')s[++i]='A'; } // 输出当前字符(A、C 或处理后的 B) cout<<s[i]; } return 0; } -
- 1
信息
- ID
- 870
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 1
- 已通过
- 1
- 上传者