目录
一、B2109 统计数字字符个数 - 洛谷
算法代码:
1. 引入库和命名空间
2. 主函数
3. 读取输入
4. 变量初始化
5. 遍历字符串
6. 输出结果
7. 返回值
总结
评测记录:
二、B2110 找第一个只出现一次的字符 - 洛谷
方法一:算法代码(使用哈希表)
1. 引入库和命名空间
2. 定义首个唯一字符的函数
3. 处理空字符串
4. 统计字符出现次数
5. 找到第一个只出现一次的字符
6. 如果没有找到唯一字符
7. 主函数
总结
方法二:算法代码(使用数组实现哈希表)
1. 引入库和命名空间
2. 定义首个唯一字符的函数
3. 处理空字符串
4. 初始化字符计数数组
5. 统计字符出现次数
6. 找到第一个只出现一次的字符
7. 如果没有找到唯一字符
8. 主函数
总结
评测记录:
三、B2112 石头剪子布 - 洛谷
算法代码:
1. 引入库
2. 主函数
3. 读取输入
4. 循环处理每局游戏
5. 读取玩家的出手
6. 判断胜负
7. 判断玩家1的胜负情况
8. 返回值
总结
评测记录:
四、B2113 输出亲朋字符串 - 洛谷
算法代码:
1. 引入库和命名空间
2. 定义生成 Friend String 的函数
3. 初始化变量
4. 遍历字符串
5. 生成新字符
6. 添加新字符到结果字符串
7. 返回结果
8. 主函数
注意
代码改进建议
总结
评测记录:
五、B2114 配对碱基链 - 洛谷
方法一:算法代码(使用map一一对应)
1. 引入库
2. 定义全局变量
3. 主函数
4. 读取输入
5. 定义碱基配对关系
6. 输出互补序列
7. 返回值
总结
方法二:算法代码(直接替换)
1. 引入库
2. 定义字符数组
3. 主函数
4. 读取输入
5. 遍历字符串并转换碱基
6. 返回值
总结
改进建议
测评记录:
六、 B2116 加密的病历单 - 洛谷
算法代码:
1. 引入库
2. 定义解密函数
3. 初始化结果字符串
4. 步骤 1:大小写反转
5. 步骤 2:逆序存储
6. 步骤 3:字符循环右移三个位置
为什么使用模运算(% 26)
7. 返回结果
8. 主函数
总结
评测记录:
七、B2117 整理药名 - 洛谷
算法代码:
1. 引入必要的库
2. 定义主函数
3. 读取字符串数量
4. 循环处理每个字符串
5. 格式化首字母为大写
6. 格式化其他字符为小写
7. 输出格式化后的字符串
8. 结束主函数
完整代码示例
总结
评测记录:
八、B2118 验证子串 - 洛谷
算法代码:
1、代码思路:
2、代码解释:
3、代码优化建议:
4、优化后的代码:
5、优化点解释:
评测记录
九、B2119 删除单词后缀 - 洛谷
算法代码:
1、代码思路:
2、具体实现步骤:
评测记录:编辑
十、 B2120 单词的长度 - 洛谷
算法代码:
引入库
定义主函数
声明变量
循环读取输入
处理第一次输入
处理后续输入
结束主函数
总结
评测记录:
一、B2109 统计数字字符个数 - 洛谷
算法代码:
#include<iostream>
#include<string>
using namespace std;int main()
{string s;getline(cin,s);int num=0;int n=s.size();for(int i=0;i<n;i++){if(s[i]>='0'&&s[i]<='9'){num++;}else{continue;}}cout<<num<<endl;
}
1. 引入库和命名空间
#include<iostream>
#include<string>
using namespace std;
-
#include <iostream>
: 引入输入输出流库,用于处理输入和输出。 -
#include <string>
: 引入字符串库,提供字符串处理功能。 -
using namespace std;
: 允许直接使用std
命名空间中的元素。
2. 主函数
int main() {
-
主程序的入口。
3. 读取输入
string s;
getline(cin, s);
-
创建一个字符串
s
。 -
使用
getline(cin, s)
从标准输入读取一整行,直到遇到换行符为止。
4. 变量初始化
int num = 0;
int n = s.size();
-
int num = 0;
: 初始化计数器num
为 0,用于统计数字字符的个数。 -
int n = s.size();
: 获取字符串s
的长度,用于后续的循环条件。
5. 遍历字符串
for(int i = 0; i < n; i++) {if(s[i] >= '0' && s[i] <= '9') {num++;} else {continue;}
}
-
使用
for
循环遍历字符串中的每个字符。 -
判断条件:
-
如果当前字符
s[i]
是数字(在'0'
到'9'
之间),则num
增加 1。 -
如果当前字符不是数字,
continue
语句将使循环继续到下一个字符,实际上这里的continue
是可以省略的,因为后面没有其他代码了。
-
6. 输出结果
cout << num << endl;
-
输出计数器
num
,即字符串中数字字符的总数。
7. 返回值
return 0;
-
返回 0,表示程序正常退出。
总结
这段代码有效地统计了输入字符串中数字字符的个数,时间复杂度为 O(n),其中 n 是字符串的长度,因为每个字符都被访问了一次。代码简单直接,适合用来进行字符统计的基本操作。
评测记录:
二、B2110 找第一个只出现一次的字符 - 洛谷
方法一:算法代码(使用哈希表)
#include <iostream>
#include <unordered_map>
using namespace std;string firstUniqueChar(const string& s) {if (s.empty()) {return "no"; // 处理空字符串}unordered_map<char, int> charCount;// 统计每个字符的出现次数for (char ch : s) {if (ch >= 'a' && ch <= 'z') { // 确保只处理小写字母charCount[ch]++;}}// 找到第一个只出现一次的字符for (char ch : s) {if (charCount[ch] == 1) {return string(1, ch); // 返回字符的字符串形式}}// 如果没有找到,返回 "no"return "no";
}int main() {string s;cin >> s;string result = firstUniqueChar(s);cout << result << endl;return 0;
}
1. 引入库和命名空间
#include <iostream>
#include <unordered_map>
using namespace std;
-
#include <iostream>
: 引入输入输出流库,用于处理输入和输出。 -
#include <unordered_map>
: 引入哈希表(无序映射)库,以便使用unordered_map
来存储字符及其出现次数。 -
using namespace std;
: 允许直接使用std
命名空间中的元素,避免在使用标准库函数时加上std::
前缀。
2. 定义首个唯一字符的函数
string firstUniqueChar(const string& s) {
-
firstUniqueChar
函数接受一个常量字符串引用s
,返回一个字符串。
3. 处理空字符串
if (s.empty()) {return "no"; // 处理空字符串
}
-
检查字符串是否为空。如果为空,则直接返回
"no"
。
4. 统计字符出现次数
unordered_map<char, int> charCount;// 统计每个字符的出现次数
for (char ch : s) {if (ch >= 'a' && ch <= 'z') { // 确保只处理小写字母charCount[ch]++;}
}
-
使用
unordered_map<char, int>
变量charCount
来存储每个字符及其出现的次数。 -
遍历字符串
s
,对于每个字符ch
:-
仅当字符是小写字母(’a’ 到 'z’)时,才对其进行统计,使用
charCount[ch]++
进行计数。
-
5. 找到第一个只出现一次的字符
for (char ch : s) {if (charCount[ch] == 1) {return string(1, ch); // 返回字符的字符串形式}
}
-
再次遍历字符串
s
,查找第一个只出现一次的字符:-
如果
charCount[ch] == 1
,则返回该字符的字符串形式(使用string(1, ch)
将字符转换为字符串)。
-
6. 如果没有找到唯一字符
return "no";
-
如果遍历结束后仍未找到任何只出现一次的字符,则返回
"no"
。
7. 主函数
int main() {string s;cin >> s;string result = firstUniqueChar(s);cout << result << endl;return 0;
}
-
主函数中读取字符串
s
,调用firstUniqueChar
函数获取结果,并输出结果。
总结
这段代码有效地找到了给定字符串中第一个只出现一次的字符,时间复杂度为 O(n),其中 n 是字符串的长度。使用 unordered_map
可以在 O(1) 时间内访问字符的计数。整体方法简单且高效,适合处理此类问题。
方法二:算法代码(使用数组实现哈希表)
#include <iostream>
#include <vector>
using namespace std;string firstUniqueChar(const string& s) {if (s.empty()) {return "no"; // 处理空字符串}vector<int> charCount(26, 0); // 初始化一个大小为26的数组,用于统计每个字母的出现次数// 统计每个字符的出现次数for (char ch : s) {if (ch >= 'a' && ch <= 'z') { // 确保只处理小写字母charCount[ch - 'a']++;}}// 找到第一个只出现一次的字符for (char ch : s) {if (ch >= 'a' && ch <= 'z' && charCount[ch - 'a'] == 1) {return string(1, ch); // 返回字符的字符串形式}}// 如果没有找到,返回 "no"return "no";
}int main() {string s;cin >> s;string result = firstUniqueChar(s);cout << result << endl;return 0;
}
1. 引入库和命名空间
#include <iostream>
#include <vector>
using namespace std;
-
#include <iostream>
: 引入输入输出流库,用于处理输入和输出。 -
#include <vector>
: 引入向量库,使得可以使用vector
容器。 -
using namespace std;
: 允许直接使用std
命名空间中的元素,避免在使用标准库函数时加上std::
前缀。
2. 定义首个唯一字符的函数
string firstUniqueChar(const string& s) {
-
firstUniqueChar
函数接受一个常量字符串引用s
,返回一个字符串。
3. 处理空字符串
if (s.empty()) {return "no"; // 处理空字符串
}
-
检查字符串是否为空。如果为空,则直接返回
"no"
。
4. 初始化字符计数数组
vector<int> charCount(26, 0); // 初始化一个大小为26的数组,用于统计每个字母的出现次数
-
创建一个大小为 26 的
vector<int>
数组charCount
,初始值都为 0。这个数组用于统计小写字母(’a’ 到 'z’)的出现次数。
5. 统计字符出现次数
for (char ch : s) {if (ch >= 'a' && ch <= 'z') { // 确保只处理小写字母charCount[ch - 'a']++;}
}
-
遍历字符串
s
,对于每个字符ch
:-
仅当字符是小写字母(’a’ 到 ‘z’)时,才对其进行统计。通过
charCount[ch - 'a']++
更新对应字母的计数。这里ch - 'a'
转换字符到数组索引(例如,’a’ 对应 0,’b’ 对应 1,以此类推)。
-
6. 找到第一个只出现一次的字符
for (char ch : s) {if (ch >= 'a' && ch <= 'z' && charCount[ch - 'a'] == 1) {return string(1, ch); // 返回字符的字符串形式}
}
-
再次遍历字符串
s
,查找第一个只出现一次的字符:-
如果字符是小写字母并且其计数为 1 (
charCount[ch - 'a'] == 1
),则返回该字符的字符串形式(使用string(1, ch)
将字符转换为字符串)。
-
7. 如果没有找到唯一字符
return "no";
-
如果遍历结束后仍未找到任何只出现一次的字符,则返回
"no"
。
8. 主函数
int main() {string s;cin >> s;string result = firstUniqueChar(s);cout << result << endl;return 0;
}
-
主函数中读取字符串
s
,调用firstUniqueChar
函数获取结果,并输出结果。
总结
这段代码有效地找到了给定字符串中第一个只出现一次的字符,时间复杂度为 O(n),其中 n 是字符串的长度。通过使用一个大小固定的数组来存储字符的计数,简化了字符计数的实现,同时提高了空间效率。这种方法简单而高效,适合处理此类问题。
评测记录:
三、B2112 石头剪子布 - 洛谷
算法代码:
#include<bits/stdc++.h>
using namespace std;
int main() {int n;cin>>n;for(int i=0; i<n; i++) {string a,b;cin>>a>>b;//读入两个字符串if(a[0]==b[0])cout<<"Tie\n";//首位相同,平局else if(a[0]=='R') {if(b[0]=='P')cout<<"Player2\n";else cout<<"Player1\n";}else if(a[0]=='P') {if(b[0]=='S')cout<<"Player2\n";else cout<<"Player1\n";}else if(a[0]=='S') {if(b[0]=='R')cout<<"Player2\n";else cout<<"Player1\n";}//以上是逐个判断,按照 Player1 的情况分类讨论//因为讨论过平局了,可以只分两种情况考虑//记得使用 else-if}return 0;
}
1. 引入库
#include <bits/stdc++.h>
using namespace std;
-
#include <bits/stdc++.h>
: 这是一个包含了大多数标准库的头文件,通常用于竞争性编程以减少代码的输入量。虽然在实际开发中不建议使用,但在比赛中常被使用。
2. 主函数
int main() {
-
程序的主入口。
3. 读取输入
int n;
cin >> n;
-
读取一个整数
n
,表示接下来要处理的对局数量。
4. 循环处理每局游戏
for (int i = 0; i < n; i++) {
-
使用
for
循环遍历每一局游戏。
5. 读取玩家的出手
string a, b;
cin >> a >> b; // 读入两个字符串
-
为每局读取两个字符串
a
和b
,分别代表玩家1和玩家2的出手。
6. 判断胜负
if (a[0] == b[0]) cout << "Tie\n"; // 首位相同,平局
-
如果玩家1和玩家2的出手相同(即两个字符串的第一个字符相同),则输出“平局”("Tie")。
7. 判断玩家1的胜负情况
else if (a[0] == 'R') {if (b[0] == 'P') cout << "Player2\n";else cout << "Player1\n";
}
else if (a[0] == 'P') {if (b[0] == 'S') cout << "Player2\n";else cout << "Player1\n";
}
else if (a[0] == 'S') {if (b[0] == 'R') cout << "Player2\n";else cout << "Player1\n";
}
-
对于玩家1的每种可能(’R’、’P’、’S’),使用
if-else
结构来判断其对应的输赢情况:-
如果玩家1出的是 'R’(石头):
-
如果玩家2出的是 'P’(布),则玩家2胜(输出 "Player2")。
-
否则,玩家1胜。
-
-
如果玩家1出的是 'P’(布):
-
如果玩家2出的是 'S’(剪子),则玩家2胜。
-
否则,玩家1胜。
-
-
如果玩家1出的是 'S’(剪子):
-
如果玩家2出的是 'R’(石头),则玩家2胜。
-
否则,玩家1胜。
-
-
8. 返回值
return 0;
-
返回 0,表示程序正常退出。
总结
这段代码实现了一个简单的“石头、剪子、布”游戏的逻辑。它通过判断两个玩家的出手情况,输出胜负结果。代码结构清晰,使用了 if-else
语句来处理不同的情况,时间复杂度为 O(n),其中 n 是输入的局数。这种实现是符合石头剪子布游戏规则的典型示例。
评测记录:
四、B2113 输出亲朋字符串 - 洛谷
算法代码:
#include <iostream>
#include <string>
using namespace std;string generateFriendString(const string& s) {string result;int n = s.length();for (int i = 0; i < n; ++i) {char newChar;if (i < n - 1) {newChar = s[i] + s[i + 1];} else {newChar = s[i] + s[0];}result += newChar;}return result;
}int main() {string inputStr;cin >> inputStr;string outputStr = generateFriendString(inputStr);cout << outputStr << endl;return 0;
}
1. 引入库和命名空间
#include <iostream>
#include <string>
using namespace std;
-
#include <iostream>
: 引入输入输出流库,用于处理输入和输出。 -
#include <string>
: 引入字符串库,以便使用string
类型。 -
using namespace std;
: 允许直接使用std
命名空间中的元素,避免在使用标准库函数时加上std::
前缀。
2. 定义生成 Friend String 的函数
string generateFriendString(const string& s) {
-
generateFriendString
函数接受一个常量字符串引用s
,返回一个字符串。
3. 初始化变量
string result;
int n = s.length();
-
创建一个空字符串
result
来存储生成的字符串。 -
获取字符串
s
的长度n
。
4. 遍历字符串
for (int i = 0; i < n; ++i) {
-
使用
for
循环遍历字符串的每个字符。
5. 生成新字符
char newChar;
if (i < n - 1) {newChar = s[i] + s[i + 1];
} else {newChar = s[i] + s[0];
}
-
创建字符变量
newChar
。 -
如果当前字符不是最后一个字符(
i < n - 1
),则将当前字符s[i]
和下一个字符s[i + 1]
相加,形成新的字符。 -
如果是最后一个字符(
i == n - 1
),则将该字符s[i]
和第一个字符s[0]
相加。
6. 添加新字符到结果字符串
result += newChar;
-
将生成的新字符
newChar
添加到结果字符串result
中。
7. 返回结果
return result;
-
返回生成的字符串。
8. 主函数
int main() {string inputStr;cin >> inputStr;string outputStr = generateFriendString(inputStr);cout << outputStr << endl;return 0;
}
-
主函数中读取输入字符串
inputStr
。 -
调用
generateFriendString
函数生成新字符串,并将结果存储在outputStr
中。 -
输出生成的字符串。
注意
需要注意的是,newChar = s[i] + s[i + 1];
这一行实际上是将两个字符的 ASCII 值相加,结果会超出字符范围并无法直接表示为字符。这将导致 newChar
并不是一个有效的字符,可能会引发未定义行为。
代码改进建议
如果想要将两个字符相加并保持在字符范围内,可以考虑将结果取模(例如,使用 % 256
),或者根据需求定义如何处理字符的组合。例如:
newChar = (s[i] + s[i + 1]) % 256; // 保持在有效字符范围内
或者,可以考虑使用字符串拼接,而不是将字符相加。具体实现取决于所需的逻辑和输出格式。
总结
这段代码时间复杂度为O(n),展示了如何基于输入字符串生成一个新字符串的基本思路,但在字符相加的部分需要谨慎处理,以确保生成的字符在有效范围内。
评测记录:
五、B2114 配对碱基链 - 洛谷
方法一:算法代码(使用map一一对应)
#include<bits/stdc++.h>
using namespace std;
char a[1000];//char型数组存字符串
int lena;
map <char,char>ch;//map一一对应
int main()
{cin>>a;lena=strlen(a);//strlen函数返回数组长度 ch['A']='T';ch['T']='A';ch['C']='G';ch['G']='C';//一一对应 for(int i=0;i<lena;i++) cout<<ch[a[i]];//输出 return 0;
}
1. 引入库
#include <bits/stdc++.h>
using namespace std;
-
#include <bits/stdc++.h>
: 这个头文件包含了几乎所有的标准库,通常在竞争性编程中使用以节省输入时间。
2. 定义全局变量
char a[1000]; // char型数组存储字符串
int lena;
map <char,char> ch; // map用于存储碱基一一对应关系
-
char a[1000];
: 定义一个字符数组a
,用于存储输入的 DNA 字符串,最大长度为 999 个字符(最后一个字符为字符串结束符\0
)。 -
int lena;
: 定义一个整数变量lena
,用于存储字符串的长度。 -
map <char,char> ch;
: 定义一个字符映射ch
,用于存储 DNA 碱基的互补关系。
3. 主函数
int main() {
-
程序的主入口。
4. 读取输入
cin >> a;
lena = strlen(a); // 用 strlen 函数返回数组长度
-
从标准输入读取一个 DNA 字符串并存储到数组
a
中。 -
使用
strlen(a)
函数获取字符串的长度,并存储在lena
中。
5. 定义碱基配对关系
ch['A'] = 'T';
ch['T'] = 'A';
ch['C'] = 'G';
ch['G'] = 'C'; // 定义碱基的互补关系
-
使用
map
来定义碱基之间的互补关系:-
‘A’ 与 ‘T’ 互补
-
‘T’ 与 ‘A’ 互补
-
‘C’ 与 ‘G’ 互补
-
‘G’ 与 ‘C’ 互补
-
6. 输出互补序列
for (int i = 0; i < lena; i++) cout << ch[a[i]]; // 输出互补序列
-
使用
for
循环遍历输入字符串的每个字符,并通过map
ch
输出互补碱基。
7. 返回值
return 0;
-
返回 0,表示程序正常退出。
总结
这段代码实现了一个简单的 DNA 互补序列生成器。它通过读取一个 DNA 序列并利用 map
存储碱基之间的互补关系,然后输出对应的互补序列。代码结构清晰,能够有效处理 DNA 碱基互补逻辑,时间复杂度为 O(n),其中 n 是输入 DNA 序列的长度。
方法二:算法代码(直接替换)
#include <bits/stdc++.h>
using namespace std;
char s[10001];
int main(){cin>>s;for (int i=0;i<strlen(s);i++)if (s[i]=='A') cout<<"T";else if (s[i]=='G') cout<<"C";else if (s[i]=='T') cout<<"A";else if (s[i]=='C') cout<<"G";return 0;
}
1. 引入库
#include <bits/stdc++.h>
using namespace std;
-
#include <bits/stdc++.h>
: 这是一个包含了大多数标准库的头文件,通常用于竞争性编程以减少代码的输入量。
2. 定义字符数组
char s[10001];
-
char s[10001];
: 定义一个字符数组s
,用于存储输入的 DNA 字符串,最大长度为 10000 个字符(最后一个字符为字符串结束符\0
)。
3. 主函数
int main() {
-
程序的主入口。
4. 读取输入
cin >> s;
-
从标准输入读取一个 DNA 字符串并将其存储在数组
s
中。
5. 遍历字符串并转换碱基
for (int i = 0; i < strlen(s); i++) {if (s[i] == 'A') cout << "T";else if (s[i] == 'G') cout << "C";else if (s[i] == 'T') cout << "A";else if (s[i] == 'C') cout << "G";
}
-
使用
for
循环遍历字符串s
的每个字符:-
如果当前字符是 'A’,则输出 'T’(A 的互补碱基)。
-
如果当前字符是 'G’,则输出 'C’(G 的互补碱基)。
-
如果当前字符是 'T’,则输出 'A’(T 的互补碱基)。
-
如果当前字符是 'C’,则输出 'G’(C 的互补碱基)。
-
6. 返回值
return 0;
-
返回 0,表示程序正常退出。
总结
这段代码实现了一个简单的 DNA 互补序列生成器。通过读取一个 DNA 序列并根据碱基的配对规则输出对应的互补碱基,它的时间复杂度为 O(n),其中 n 是输入 DNA 序列的长度。
改进建议
尽管这段代码功能正常,但有几个改进点可以考虑:
-
使用
strlen
的优化:每次调用strlen(s)
会遍历整个字符串,导致效率下降。可以在循环开始前缓存字符串的长度:int len = strlen(s); for (int i = 0; i < len; i++) { ... }
-
使用
switch
语句:使用switch
语句可以使代码更简洁、易读:switch (s[i]) {case 'A': cout << "T"; break;case 'G': cout << "C"; break;case 'T': cout << "A"; break;case 'C': cout << "G"; break; }
-
输入限制:可以加上对输入字符串的有效性检查,确保只有合法的 DNA 碱基被处理。
-
输出格式:在某些情况下,可能需要换行或分隔符来格式化输出。
以下是改进后的代码示例:
#include <bits/stdc++.h>
using namespace std;char s[10001];int main() {cin >> s;int len = strlen(s); // 缓存字符串长度for (int i = 0; i < len; i++) {switch (s[i]) {case 'A': cout << "T"; break;case 'G': cout << "C"; break;case 'T': cout << "A"; break;case 'C': cout << "G"; break;}}return 0;
}
通过这些改进,代码会更加高效和清晰。
测评记录:
六、 B2116 加密的病历单 - 洛谷
算法代码:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;string decryptString(const string& s) {string result = s;// 1. 大小写反转for (char& c : result) {if (isupper(c)) {c = tolower(c);} else if (islower(c)) {c = toupper(c);}}// 2. 逆序存储reverse(result.begin(), result.end());// 3. 字符循环右移三个位置for (char& c : result) {if (isalpha(c)) {if (isupper(c)) {c = 'A' + (c - 'A' + 3) % 26;} else {c = 'a' + (c - 'a' + 3) % 26;}}}return result;
}int main() {string inputStr;cin >> inputStr;string outputStr = decryptString(inputStr);cout << outputStr << endl;return 0;
}
1. 引入库
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
-
#include <iostream>
: 引入输入输出流库,用于处理输入和输出。 -
#include <string>
: 引入字符串库,以便使用string
类型。 -
#include <algorithm>
: 引入算法库,以便使用标准算法,例如reverse
。
2. 定义解密函数
string decryptString(const string& s) {
-
decryptString
函数接受一个常量字符串引用s
,返回一个解密后的字符串。
3. 初始化结果字符串
string result = s;
-
创建一个新的字符串
result
,并将输入字符串s
复制到result
中。
4. 步骤 1:大小写反转
for (char& c : result) {if (isupper(c)) {c = tolower(c);} else if (islower(c)) {c = toupper(c);}
}
-
使用范围
for
循环遍历result
中的每个字符c
:-
如果
c
是大写字母,则将其转换为小写字母。 -
如果
c
是小写字母,则将其转换为大写字母。
-
5. 步骤 2:逆序存储
reverse(result.begin(), result.end());
-
使用
reverse
函数将result
字符串中的字符顺序反转。
6. 步骤 3:字符循环右移三个位置
for (char& c : result) {if (isalpha(c)) {if (isupper(c)) {c = 'A' + (c - 'A' + 3) % 26;} else {c = 'a' + (c - 'a' + 3) % 26;}}
}
-
再次使用范围
for
循环遍历result
中的每个字符c
:-
检查字符是否为字母(
isalpha(c)
)。 -
如果是大写字母,计算循环右移后的新字符:
-
使用
c - 'A'
将字母转换为 0 到 25 的范围,加上 3 后再取模 26,最后通过'A' +
将其转换回字符。
-
-
如果是小写字母,执行相同的操作,但使用
'a'
为基准。为什么使用模运算(
% 26
) -
字母表有 26 个字母(A-Z 或 a-z),因此字符的偏移量必须在 0 到 25 之间。
-
当字符的偏移量增加 3 后,可能会超出 25(例如,
'x'
的偏移量是 23,增加 3 后变为 26)。 -
使用模运算
% 26
可以确保偏移量循环回到字母表的开头:-
例如,
26 % 26 = 0
,对应字母'a'
或'A'
。 -
这样,字符的移动是循环的,不会超出字母表的范围。
-
-
7. 返回结果
return result;
-
返回解密后的字符串。
8. 主函数
int main() {string inputStr;cin >> inputStr;string outputStr = decryptString(inputStr);cout << outputStr << endl;return 0;
}
-
主函数中读取输入字符串
inputStr
。 -
调用
decryptString
函数生成解密后的字符串,并将结果存储在outputStr
中。 -
输出解密后的字符串。
总结
这段代码有效地实现了一种字符串解密的方式。通过对输入字符串进行大小写反转、逆序和字符循环右移三个步骤,生成了新的字符串。时间复杂度为 O(n),其中 n 是输入字符串的长度。
评测记录:
七、B2117 整理药名 - 洛谷
算法代码:
#include<bits/stdc++.h>
using namespace std;
int n,lena;
char a[30];//char型数组存字符串
int main()
{cin>>n;for(int i=0;i<n;i++){cin>>a;lena=strlen(a);;//strlen返回char型数组的长度if(islower(a[0])) a[0]-=32;//判断开头字符是否是小写字母,若是,则转化为大写for(int j=1;j<lena;j++) if(isupper(a[j])) a[j]+=32;//判断其他字符是否为大写字母,若是,则转化为小写cout<<a<<endl;}return 0;
}
1. 引入必要的库
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
-
引入
<iostream>
进行输入输出操作。 -
引入
<string>
以使用 C++ 的string
类型。 -
引入
<algorithm>
以使用一些算法函数,比如toupper
和tolower
。
2. 定义主函数
int main() {
-
定义程序的主入口。
3. 读取字符串数量
int n;
cin >> n;
cin.ignore(); // 忽略换行符
-
声明一个整数
n
用于存储将要处理的字符串数量。 -
使用
cin >> n;
读取数量。 -
使用
cin.ignore();
忽略后续的换行符,以便正确读取字符串。
4. 循环处理每个字符串
for (int i = 0; i < n; i++) {string a;getline(cin, a); // 使用 getline 读取字符串
-
使用
for
循环遍历每个字符串。 -
声明一个
string
类型的变量a
来存储当前字符串。 -
使用
getline(cin, a);
读取整行输入的字符串。
5. 格式化首字母为大写
if (islower(a[0])) {a[0] = toupper(a[0]); // 将首字母转为大写
}
-
检查字符串的第一个字符是否为小写字母(
islower
)。 -
如果是,则使用
toupper
将其转换为大写。
6. 格式化其他字符为小写
for (int j = 1; j < a.length(); j++) {a[j] = tolower(a[j]); // 将剩余字符转为小写
}
-
使用
for
循环遍历从第二个字符开始的每个字符。 -
使用
tolower
将每个大写字母转换为小写。
7. 输出格式化后的字符串
cout << a << endl; // 输出结果
-
输出格式化后的字符串
a
。
8. 结束主函数
return 0;
}
-
使用
return 0;
表示程序正常结束。
完整代码示例
#include <iostream>
#include <string>
#include <algorithm>using namespace std;int main() {int n;cin >> n;cin.ignore(); // 忽略换行符for (int i = 0; i < n; i++) {string a;getline(cin, a); // 使用 getline 读取字符串// 将首字母转为大写if (islower(a[0])) {a[0] = toupper(a[0]);}// 将剩余字符转为小写for (int j = 1; j < a.length(); j++) {a[j] = tolower(a[j]);}cout << a << endl; // 输出结果}return 0;
}
总结
程序的时间复杂度是 ( O(n \cdot L) ),其中 ( n ) 是字符串的数量,( L ) 是每个字符串的平均长度。
评测记录:
八、B2118 验证子串 - 洛谷
算法代码:
#include<bits/stdc++.h>
using namespace std;
string a,b;
int main()
{cin>>a>>b;if(a.find(b)!=a.npos) //如果b是a的子串 {cout<<b<<" is substring of "<<a<<endl;}else if(b.find(a)!=b.npos) //如果a是b的子串 {cout<<a<<" is substring of "<<b<<endl;}else //如果没有子串关系 {cout<<"No substring"<<endl;}return 0;
}
1、代码思路:
-
输入两个字符串:从标准输入读取两个字符串
a
和b
。 -
判断子串关系:
-
使用
a.find(b)
检查b
是否是a
的子串。 -
如果
b
是a
的子串,输出b is substring of a
。 -
否则,使用
b.find(a)
检查a
是否是b
的子串。 -
如果
a
是b
的子串,输出a is substring of b
。 -
如果两者都不是对方的子串,输出
No substring
。
-
-
结束程序:返回 0,表示程序正常结束。
2、代码解释:
-
a.find(b)
:在字符串a
中查找子串b
。如果找到,返回子串的起始位置;否则返回string::npos
。 -
b.find(a)
:在字符串b
中查找子串a
。如果找到,返回子串的起始位置;否则返回string::npos
。 -
if-else
结构:根据查找结果判断子串关系,并输出相应的信息。
3、代码优化建议:
-
输入处理:确保输入的两个字符串不为空,避免不必要的错误。
-
大小写敏感:如果希望忽略大小写,可以在查找前将字符串统一转换为小写或大写。
-
边界情况:考虑空字符串的情况,避免程序崩溃。
4、优化后的代码:
#include<bits/stdc++.h>
using namespace std;int main()
{string a, b;cin >> a >> b;if (a.empty() || b.empty()) {cout << "No substring" << endl;return 0;}if (a.find(b) != string::npos) {cout << b << " is substring of " << a << endl;} else if (b.find(a) != string::npos) {cout << a << " is substring of " << b << endl;} else {cout << "No substring" << endl;}return 0;
}
5、优化点解释:
-
空字符串检查:在查找子串之前,检查
a
和b
是否为空字符串。如果为空,直接输出No substring
。 -
代码简洁性:保持代码逻辑清晰,易于理解。
评测记录
九、B2119 删除单词后缀 - 洛谷
算法代码:
#include <iostream>
#include <string>using namespace std;string removeSuffix(const string& word) {if (word.length() >= 2 && word.substr(word.length() - 2) == "er") {return word.substr(0, word.length() - 2);}if (word.length() >= 2 && word.substr(word.length() - 2) == "ly") {return word.substr(0, word.length() - 2);}if (word.length() >= 3 && word.substr(word.length() - 3) == "ing") {return word.substr(0, word.length() - 3);}return word;
}int main() {string word;cin >> word;cout << removeSuffix(word) << endl;return 0;
}
1、代码思路:
-
输入处理:
-
从标准输入读取一个单词。
-
确保单词的长度不超过题目要求的最大长度(32个字符)。
-
-
后缀检查与删除:
-
检查单词是否以
er
结尾。如果是,删除最后两个字符。 -
检查单词是否以
ly
结尾。如果是,删除最后两个字符。 -
检查单词是否以
ing
结尾。如果是,删除最后三个字符。 -
如果单词不以任何指定的后缀结尾,则保持不变。
-
-
输出结果:
-
输出处理后的单词。
-
2、具体实现步骤:
-
读取输入:
-
使用
cin
读取输入的单词。
-
-
后缀检查:
-
使用
substr
方法检查单词的最后几个字符是否与目标后缀匹配。 -
如果匹配,使用
substr
方法删除后缀。
-
-
输出结果:
-
使用
cout
输出处理后的单词。
-
评测记录:
十、 B2120 单词的长度 - 洛谷
算法代码:
#include <bits/stdc++.h>using namespace std;int main() {string s;bool flag = true;while (cin >> s) {if (flag) {flag = false;cout << s.size();} else {cout << ',' << s.size();}}return 0;
}
-
引入库
#include <bits/stdc++.h>
-
引入标准库,提供各种数据结构和算法的支持。
-
-
定义主函数
int main() {
-
程序的主入口。
-
-
声明变量
string s; bool flag = true;
-
声明一个字符串变量
s
用于存储输入的每个单词。 -
声明一个布尔变量
flag
,初始值为true
,用于控制输出格式。
-
-
循环读取输入
while (cin >> s) {
-
使用
while
循环从标准输入中读取字符串s
,直到输入结束。
-
-
处理第一次输入
if (flag) {flag = false;cout << s.size(); }
-
在第一次读取字符串时(即
flag
为true
),输出字符串s
的长度,并将flag
设置为false
,以便后续输入的处理。
-
-
处理后续输入
else {cout << ',' << s.size(); }
-
对于后续读取的字符串,输出一个逗号
,
,然后输出字符串s
的长度。
-
-
结束主函数
return 0; }
-
返回 0,表示程序正常结束。
-
总结
该程序的功能是从标准输入中逐个读取字符串,并输出每个字符串的长度。对于第一个字符串,它直接输出长度;对于后续的字符串,它在长度前添加一个逗号分隔符。最终输出的是所有输入字符串长度的逗号分隔列表。综上所述,循环体内的操作(读取字符串、计算长度和输出长度)都是 ( O(1) ) 的,因此整个程序的时间复杂度为: [ O(n) ] 其中 ( n ) 是输入中字符串的数量。也就是说,程序的运行时间是线性于输入字符串数量的。