第十八节 小组学习
AT_agc022_a 题解
本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读。
题目简述
给定字符串 \(S\) , 仅包含互不相同的小写字母, 你需要找到仅包含互不相同的小写字母的字符串中,第一个字典序比它大的字符串, 如果找不到输出 \(-1\)。(\(| S | \le 26\))
思路
这篇题解主要分享一下 map
的做法。
可分两种情况讨论:
-
字符串长度 \(< 26\)。
-
字符串长度 \(= 26\)。
因为互不相同所以不会出现大于 \(26\) 的情况。
对于样例 \(4\):abcdefghijklmnopqrstuvwzyx
。
可将 w
变为它后面比它大但最小的 x
,后面直接舍去即可,变为 abcdefghijklmnopqrstuvx
。
解释完样例,先来讨论一下情况 \(1\),因为长度小于 \(26\),所以至少有 \(1\) 个字母未出现过,直接在字符串末尾加上没出现过的最小字母即可。
对于情况 \(2\),就可参考以上样例 \(4\) 的解释,可发现找到一个位置,把这个位置上的字母替换为它后面比它大但最小的字母即可,这个位置需要从后向前枚举。
那么接下来就是实现了,首先需要定义一个 map
容器,来存储哪些字母出现过或没出现过,对于情况 \(1\) 直接模拟即可。
对于情况 \(2\) 则需记录一个最大值,如果当前位置小于最大值再枚举,这样就避免了不合法的情况了。
经过以上分类讨论,很容易即可写出代码了:
#include<iostream>
#include<map>
using namespace std;
string str;
int maxn;
map<char, int> mp;
map<int, bool> vis;
int max(int x, int y) { return (x > y) ? x : y; }
int main() {
cin >> str;
int n = str.length(); // 记录长度
for(int i = 0; i < n; i ++) mp[str[i]] ++; // 计数
if(n < 26) {
for(int i = 'a'; i <= 'z'; i ++)
if(!mp[i]) {
cout << str << char(i) << endl; // 没有出现过,直接输出结束
return 0;
}
}
// 从后向前枚举
for(int i = n - 1; i >= 0; i --) {
// 满足条件,可输出
if(str[i] < maxn) {
for(int j = 0; j < i; j ++) cout << str[j];
for(int j = str[i] - 'a'; j < 26; j ++)
if(vis[j]) {
cout << char(j + 'a'); // 输出替换的字母
return 0;
}
}
maxn = max(maxn, str[i]);
vis[str[i] - 'a'] = true;
}
cout << "-1\n"; // 以上条件都不满足,输出 -1
return 0;
}
CF858C 题解
本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读。
题目简述
给你一个均为小写字母的字符串,如果它的子串同时满足:
-
三个连着的辅音字母。
-
这一段连着的辅音字母不是全部一样的。
就认为它不合法。
现在要求用最少的空格隔开这个字符串,使得它变成合法的。
思路
首先定义记录当前位置是否是元音字母的数组 \(a\),并维护它,如下:
for(int i = 0; i < n; i ++) {
bool flag = false;
for(int j = 0; j < 5; j ++)
if(str[i] == c[j]) flag = true;
a[i] = flag;
}
接着直接根据题目要求模拟即可,定义 \(num\) 记录当前连续辅音字母的个数,当这个个数 \(\ge 3\) 之后输出空格即可,这里需要注意:需要先输出空格再输出字母!
经过以上分析及代码片段,很容易即可写出代码了:
#include<iostream>
using namespace std;
char c[10] = {'a', 'e', 'i', 'o', 'u'}; // 元音字母数组
string str;
bool a[3005]; // 记录是否是元音字母
int main(){
cin >> str;
int n = str.length();
// 预处理 a 数组
for(int i = 0; i < n; i ++) {
bool flag = false;
for(int j = 0; j < 5; j ++)
if(str[i] == c[j]) flag = true;
a[i] = flag;
}
int num = !a[0]; // 初始化 num
cout << str[0]; // 先输出第一个字母
for(int i = 1; i < n; i ++) {
// 如果是辅音字母
if(!a[i]) {
num ++; // 增加计数
if(num >= 3 && !(str[i - 2] == str[i] && str[i - 1] == str[i])) {
cout << ' '; // 满足条件输出空格
num = 1; // num 初始化
}
}
else num = 0; // 元音字母
cout << str[i]; // 正常输出
}
return 0;
}
本文来自博客园,作者:So_noSlack,转载请注明原文链接:https://www.cnblogs.com/So-noSlack/p/17589327.html