一些字符串题目

题目

字符间也可以稳定排序,利用一个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;
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务