一些字符串题目
字符间也可以稳定排序,利用一个pair保存字符与输入次序,全部转为小写(可判断是大写还是小写,是大写+=32或使用tolower,转换为小写就可以实现不区分大小写排序,若大小写同时存在则按输入顺序先后排序)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool isLetter(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
bool cmp(const pair<int, char>& a, const pair<int, char>& b){
char lowerA = tolower(a.second);
char lowerB = tolower(b.second);
if(lowerA < lowerB){
return true;
}else if(lowerA == lowerB && a.first < b.first){
return true;
}else {
return false;
}
}
int main() {
string input;
while (getline(cin, input)) {
vector<pair<int, char>> letters;
// 提取所有字母及其位置
for (int i = 0; i < input.size(); i++) {
if (isLetter(input[i])) {
letters.push_back({i, input[i]}); // 或使用makepair(i, input[i])
}
}
// 按规则排序字母
sort(letters.begin(), letters.end(), cmp);
// 重构字符串
int cnt = 0;
for (int i = 0; i < input.size(); i++) {
if (isLetter(input[i])) {
input[i] = letters[cnt++].second;
}
}
cout << input << endl;
}
return 0;
}
find与erase配合使用,循环删除子串中特定字符串(本题不需要两个参数的find版本,因为每查找到一个目标子串就删掉了,因此能够保证找到字符串中所有目标子串)
#include <string>
#include <iostream>
using namespace std;
int main() {
string str1, str2;
while (cin >> str1 >> str2) {
int pos = 0;
while ((pos = str1.find(str2)) != string::npos) {
str1.erase(pos, str2.size());
}
cout << str1 << endl;
}
return 0;
}
find两个参数,可实现从pos处开始查找(s.find(temp, pos)
)
(pos = s.find(temp, pos)) != string::npos
是因为赋值表达式本身会返回被赋值的值,因此在find的结果会被赋给pos,并返回这个值再与npos比较看是否找到了
- 会先执行
pos = s.find(temp, pos)
,将查找结果赋值给pos
。 - 然后判断赋值表达式的返回值(即
pos
的值)是否等于string::npos
。
查找的子串允许重叠不允许重叠(默认是可重叠,即从以匹配字符串的起始下标的下一个位置继续比较)
while ((pos = s.find(temp, pos)) != string::npos) {
count[temp]++;
pos++;
}
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
string s;
while (cin >> s) {
map<string, int> count;
// 外层i表示子串起点,内层一直从起点及以后遍历到末尾
for (int i = 0; i < s.size(); i++) {
string temp = "";
for (int j = i; j < s.size(); j++) {
temp += s[j];
int pos = 0;
// 允许重叠,若不允许重叠pos+=temp.size()
// find两个参数,从pos处开始查找
if (count.find(temp) == count.end()) { // 如果之前已经统计过该字符串无需再统计
while ((pos = s.find(temp, pos)) != string::npos) {
count[temp]++;
pos++;
}
}
}
}
for (auto it = count.begin(); it != count.end(); it++) {
if (it->second > 1) {
cout << it->first << " " << it->second << endl;
}
}
}
return 0;
}
除了会用map保存映射关系,也要会用pair保存映射关系(不需要排序的场景)
#include <utility> // pair 的头文件
vector<pair<char, int>> count;
count.push_back(make_pair(cmp, cnt));
for (auto it = count.begin(); it != count.end(); it++) {
cout << it->first << " " << it->second << endl;
}
#include <iostream>
#include <string>
#include <vector>
#include <utility> // pair 的头文件
using namespace std;
int main() {
string str1, str2;
// 用map默认会按键升序排序对于本题不合适,用vector和pair组合实现按字符顺序统计每一位字符出现的次数
while (getline(cin, str1) && getline(cin, str2)) {
vector<pair<char, int>> count;
if (str1 == "#") {
break;
}
for (int i = 0; i < str1.size(); i++) {
char cmp = str1[i];
int pos = 0;
int cnt = 0;
while ((pos = str2.find(cmp, pos)) != string::npos) {
cnt++;
pos++;
}
count.push_back(make_pair(cmp, cnt));
}
// 输出结果
for (auto it = count.begin(); it != count.end(); it++) {
cout << it->first << " " << it->second << endl;
}
}
return 0;
}
reverse不是string的成员函数,是STL算法,传要翻转容器(string,vector等)的首尾范围迭代器
replace属于string的成员函数,第一个参数是要开始替换的起始下标,第二个参数是要替换的长度,最后一个参数是要替换的目标字符串
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
string str;
int n;
cin >> str >> n;
while (n--) {
string op;
cin >> op;
int begin = op[1] - '0';// 起始下标
int len = op[2] - '0'; // 要操作的字符串长度
if (op[0] == '0') { // 翻转,将首尾迭代器范围内左闭右开的字符全部翻转
reverse(str.begin() + begin, str.begin() + begin + len);
}
else if (op[0] == '1') { // 替换,第一个参数写要替换的起始下标,第二个参数写长度,第三个参数写目标字符串
str.replace(begin, len, op.substr(3));
}
cout << str << endl;
}
return 0;
}
用字符串模拟大数加法,都先对其对齐位数,s1.insert(0, 1, '0');
表示在开头处pos=0处插入1个'0',while循环运行直至两个字符串位数相同;随后从低位开始相加,若超过10就进位并设置标记,最后最高位若还有进位也要push在最终结果中
#include <iostream>
#include <string>
#include <cmath>
#include <vector>
using namespace std;
int main() {
string s1, s2;
while (cin >> s1 >> s2) {
// 在高位补0对齐位数
while (s1.size() < s2.size()) {
s1.insert(0, 1, '0');
}
while (s1.size() > s2.size()) {
s2.insert(0, 1, '0');
}
vector<int> ans;
bool carry = false;
// 从低位开始十进制加法
for (int i = s1.size() - 1, j = s2.size() - 1; i >= 0 && j >= 0; --i, --j) {
int sum = s1[i] - '0' + s2[j] - '0';
if (carry) sum += 1;
if (sum >= 10) {
ans.push_back(sum - 10);
carry = true;
continue;
}
ans.push_back(sum);
carry = false;
}
// 如果最高位仍有进位,加到结果中
if (carry) ans.push_back(1);
// 输出结果
for (auto it = ans.rbegin(); it != ans.rend(); it++) {
cout << *it;
}
cout << endl;
}
return 0;
}