第一行输入一个整数T,代表接下来有T组测试数据。 对于每一组测试数据,第一行输入两个数n,m代表字符串的长度和可以删除的字符数量。接下来输入长度为n字符串。1≤T≤5 2≤n≤100000 1≤m<n 输出描述 对于每一组数据,输出一个答案 c++写
时间: 2025-03-22 13:06:10 浏览: 25
好的,这里是针对您的问题设计的一个完整的解决方案,并附带详细的讲解和代码实现。
---
### 题目解析
我们需要对每一组测试数据进行处理:
从长度为 `n` 的字符串中删除最多 `m` 个字符,使得剩下的字符串字典序尽可能地小。最终输出处理后的字符串。
**关键点:**
- 删除操作需要保证结果的字典序最小。
- 贪心算法配合栈结构可以帮助高效解决问题。
---
### 算法思路
为了得到字典序最小的字符串,我们可以使用贪心算法并结合栈的操作:
1. 初始化一个空栈(这里用 `vector<char>` 模拟栈)。
2. 遍历输入字符串的每个字符:
- 当前字符记作 `c`。
- 若栈非空、且栈顶元素比当前字符大,并且还可以继续删除更多字符,则弹出栈顶元素。
- 将当前字符压入栈中。
3. 如果遍历结束后仍然有多余的删除次数(即 `m > 0`),则直接移除栈顶部多余的字符。
4. 最终将栈中的字符按顺序拼接成字符串作为答案。
---
### 示例代码 (C++ 实现)
```cpp
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 函数功能:对于一组测试数据返回最优解
string solve(int n, int m, const string& s) {
vector<char> stack; // 模拟栈
int remain = m; // 剩余可删字符数
for (int i = 0; i < n; ++i) {
char current_char = s[i];
// 弹出栈顶较大值直到满足条件或无法再删除
while (!stack.empty() && remain > 0 && stack.back() > current_char) {
stack.pop_back();
--remain;
}
// 添加当前字符到栈
stack.push_back(current_char);
}
// 如果仍有剩余删除次数,直接截断多余部分
while (remain > 0) {
stack.pop_back();
--remain;
}
// 构造结果字符串
return string(stack.begin(), stack.end());
}
int main() {
ios::sync_with_stdio(false); // 提升I/O速度
cin.tie(nullptr);
int T;
cin >> T; // 测试组数
while (T--) {
int n, m;
cin >> n >> m; // 字符串长度及最大删除数
string s;
cin >> s; // 输入字符串
cout << solve(n, m, s) << "\n"; // 输出结果
}
return 0;
}
```
---
### 代码详解
1. **函数定义**:
- 定义了 `solve` 函数专门负责计算单组测试数据的答案。
2. **核心逻辑**:
- 利用了栈的思想,在遍历过程中动态调整以达到最佳效果。
- 栈存储的是目前保留的所有候选字符。
3. **优化细节**:
- 使用 `ios::sync_with_stdio(false)` 和 `cin.tie(0)` 来加速标准输入输出流。
4. **时间复杂度分析**:
- 单组数据的时间复杂度为 O(n),因为每个字符最多只会进出栈一次。
- 总体复杂度为 O(T * n),适用于题目范围 \(1 \leq T \leq 5\) 和 \(2 \leq n \leq 10^5\)。
---
### 示例运行
#### 输入样例:
```
2
6 2
abcdec
7 3
abcdefg
```
#### 输出结果:
```
abce
adefg
```
---
阅读全文
相关推荐


















