PAT-字符串(AcWingPAT甲级课笔记)

目录

1001 A+B Format

1005 Spell It Right

1006 Sign In and Sign Out

1035 Password

1036 Boys vs Girls

1050 String Subtraction

1071 Speech Patterns

1061 Dating

1016 Phone Bills

1060 Are They Equal

1073 Scientific Notation

1077 Kuchiguse

1082 Read Number in Chinese

1084 Broken Keyboard

1108 Finding Average

1124 Raffle for Weibo Followers

1141 PAT Ranking of Institutions

1153 Decode Registration Card of PAT


思维能力:

快速想出解题思路,用什么数据结构存,用什么枚举方式求出来

代码熟练度:

快速写出代码并调试通过

1001 A+B Format

注意点

注意拼接顺序,是num[i] + res 还是 res + num[i]

#include<iostream>

using namespace std;

int main(){
    int a,b;
    cin >> a >> b; //存a和b
    int c = a+b;  
    string num = to_string(c);
    string res;

    for (int i = num.size() - 1, j = 0 ; i >= 0; i--) 
    {
        res = num[i] + res; //从最后一位开始拼接
        ++ j;
        if(j % 3 == 0 && i && num[i-1] != '-') res = ',' + res;   //每3位填一个‘,’
    }
    cout << res;

    return 0;
}

1005 Spell It Right

注意点

1.二维char数组的用法

2.行末空格的处理手法

#include<iostream>

using namespace std;

int main() {
    string n;
    cin >> n;

    int sum = 0; 
    for(auto c : n) sum += c - '0';  // -'0' 把字符‘1’转成数字 1

    string str = to_string(sum);

    char word[10][10] = {           
        "zero","one","two","three","four",
        "five","six","seven","eight","nine",
    };

    cout << word[str[0] - '0'];   //先输出第一个
    for (int i = 1; i < str.size(); i++){
        cout << " " << word[str[i] - '0'];  //每个先输出空格 再输出字符 这样最后一位不会多一个空格
    }
    
    return 0;
}

1006 Sign In and Sign Out

注意点

HH:MM:SS 看成字符串

#include<iostream>
using namespace std;

int main(){
    string open_id,open_time;
    string close_id,close_time;

    int m;
    cin >> m;

    for (int i = 0; i < m; i++){
        string id,in_time,out_time;
        cin >> id >> in_time >> out_time;

        if(!i || in_time < open_time){    //i=0 第一个时 直接赋值  HH:MM:SS位数相同,都是两位两位比,先比较H再比较M,按字典序比
            open_id = id;                 //默认string的比较就是按字典序比的
            open_time = in_time;
        }
        if(!i || out_time > close_time){
            close_id = id;
            close_time = out_time;
        }
    }
    cout << open_id << " " << close_id << endl;


    return 0;
}


1035 Password

单词:

lowercase 小写

uppercase 大写

#include<iostream>

using namespace std;

const int N = 1010;

string name[N],pwd[N];

string change(string str){  //修改密码
    string res;

    for(auto c : str){
        if(c == '1') res += '@';
        else if (c == '0') res += '%';
        else if (c == 'l') res += 'L';
        else if (c == 'O') res += 'o';
        else res += c;
    }

    return res;
}

int main(){
    int n;
    cin >> n;

    int m = 0;   
    for (int i = 0; i < n; i++){
        string cur_name, cur_pwd;
        cin >> cur_name >> cur_pwd;
        string changed_pwd = change(cur_pwd);

        if(changed_pwd != cur_pwd){
            name[m] = cur_name;
            pwd[m] = changed_pwd;
            m++;
        }
    }
    
    if(!m){
        if(n == 1) {
            printf("There is 1 account and no account is modified");
        }else {
            printf("There are %d accounts and no account is modified", n);
        }
    }else{
        cout << m << endl;
        for (int i = 0; i < m; i++){
            cout << name[i] << " " << pwd[i] << endl;
        }
        
    }

    return 0;
}


1036 Boys vs Girls

#include<iostream>

using namespace std;

int main(){
    int n;

    string girl_name,girl_id; //女生第一名的信息
    int girl_score;
    string boy_name,boy_id; //男生第一名的信息
    int boy_score;

    cin >> n;
    for (int i = 0; i < n; i++){
        string name,sex,id;
        int score;
        cin >> name >> sex >> id >> score;

        if(sex == "F"){  //如果当前同学是女生
            if(girl_name.empty() || girl_score < score){
                girl_name = name;
                girl_id = id;
                girl_score = score;
            }
        }else{  //当前同学是男生
            if(boy_name.empty() || boy_score > score){
                boy_name = name;
                boy_id = id;
                boy_score = score;
            }
        }
    }
    if(girl_name.empty()) puts("Absent");
    else cout << girl_name << ' ' << girl_id << endl;

    if(boy_name.empty()) puts("Absent");
    else cout << boy_name << ' ' << boy_id << endl;

    if(girl_name.size() && boy_name.size()){
        cout << abs(girl_score - boy_score);
    }else{
        cout << "NA" << endl;
    }

    return 0;
}


1050 String Subtraction


解法1: 暴力解

#include<iostream>
using namespace std;

string s1,s2;
//暴力
bool check_exists(char c){
    for(auto a : s2){
        if(a == c){
            return true;
        }
    }
    return false;

}
int main(){
    getline(cin , s1);  //读入带空格的字符串
    getline(cin , s2);

    string res;
    for(auto c : s1){
        if(!check_exists(c)){
            res += c;
        }
    }
    cout << res << endl;
    
    return 0;
}


解法2: 快速解(hashset)

注意点

读入带有空格的string 用getline

#include<iostream>
#include<unordered_set>

using namespace std;

string s1, s2;

//优化 用哈希表
int main(){
    getline(cin , s1);  
    getline(cin , s2);

    unordered_set<char> set; //定义hash
    //不允许有重复的元素,出现过就是1,没出现过就是0
    for(auto c : s2) set.insert(c); //将s2中的字符插入hash表

    string res;
    for(auto c : s1){
        if(!set.count(c)){
            res += c;
        }
    }
    cout << res << endl;
    
    return 0;
}


1071 Speech Patterns

单词:

synonyms 同义

validating 验证

解析

1.getline读入一整行

2.提取每一个单词,双指针写法,再存到哈希表里统计个数

3.遍历整个哈希表,找到出现次数最多的单词

注意点

除数字和字母,其他都不算单词。

tolower() 转换为小写字母

#include<iostream>
#include<unordered_map>

using namespace std;

bool check(char c){  //判断是否是字母
    if(c >= '0' && c <= '9') return true;
    if(c >= 'A' && c <= 'Z') return true;
    if(c >= 'a' && c <= 'z') return true;
    return false;
}

char to_lower(char c){  //大写转小写,已经是小写则不变
    if(c >= 'A' && c <= 'Z') return c + 32;
    return c; 
}
int main(){
    string str;
    getline(cin, str);

    unordered_map<string, int> hashmap;

    for(int i = 0; i < str.size(); i++)
        if(check(str[i])){
            string word;
            int j = i;
            while(j < str.size() && check(str[j])) word += to_lower(str[j++]); //也可直接用tolower函数

            hashmap[word]++;
            i = j;
        }
    string word;
    int cnt = -1;
    for(auto item : hashmap)
        if(item.second > cnt || item.second == cnt && item.first < word){
            word = item.first;
            cnt = item.second;
        }
    cout << word << ' ' << cnt << endl;
    return 0;	
}

1061 Dating

单词:

case sensitive 区分大小写

capital letter 大写字母

注意点

1、一对字符相同,是指在两个字符相同且在字符串的位置也相同。
2、前两个字符串中第一对相同的大写英文字母,是指第一对能够正确代表日期的大写英文字母。
3、前两个字符串中第二对相同的字符,是指位于代表日期的字符后面的,第一对相同的,能够正确代表小时的字符。

不足两位要补0。

#include <cstdio>
#include <iostream>

using namespace std;

int main(){
    string a, b, c, d;
    cin >> a >> b >> c >> d;

    int k = 0;
    while (true){  //题目说了一定有结果
        if (a[k] == b[k] && a[k] >= 'A' && a[k] <= 'G') break;
        k ++ ;
    }

    char weekdays[7][4] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
    printf("%s ", weekdays[a[k] - 'A']);

    k ++ ;  //k往后走一个,继续往后找第二个满足要求的字母 
    while (true){
        if (a[k] == b[k] && ((a[k] >= '0' && a[k] <= '9' ) || (a[k] >= 'A' && a[k] <= 'N'))) break;
        k ++ ;
    }

    printf("%02d:", a[k] <= '9' ? a[k] - '0' : a[k] - 'A' + 10);

    for (int i = 0;; i ++ )
        if (c[i] == d[i] && ((c[i] >= 'a' && c[i] <= 'z') || (c[i] >= 'A' && c[i] <= 'Z'))){
            printf("%02d\n", i);
            break;
        }

    return 0;
}


1016 Phone Bills

注意点

1美元 = 100美分

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>

using namespace std;

const int N = 1010, M = 31 * 1440 + 10;

int n;
int cost[24];  // 每个时间段的话费
double sum[M];  // 从当月1号00:00开始到每个时刻所花费的钱数

struct Record{
    int minutes;        //时间
    string state;       //状态
    string format_time;  //格式化时间

    bool operator< (const Record& t) const{
        return minutes < t.minutes;
    }
};

map<string, vector<Record>> persons;

int main(){
    for (int i = 0; i < 24; i ++ ) cin >> cost[i];
    for (int i = 1; i < M; i ++ ) sum[i] = sum[i - 1] + cost[(i - 1) % 1440 / 60] / 100.0;

    cin >> n;
    char name[25], state[10], format_time[20];
    int month, day, hour, minute;
    for (int i = 0; i < n; i ++ ){
        scanf("%s %d:%d:%d:%d %s", name, &month, &day, &hour, &minute, state);
        sprintf(format_time, "%02d:%02d:%02d", day, hour, minute);

        int minutes = (day - 1) * 1440 + hour * 60 + minute;
        persons[name].push_back({minutes, state, format_time});
    }

    for (auto &person : persons){
        auto name = person.first;
        auto records = person.second;
        sort(records.begin(), records.end());

        double total = 0;
        for (int i = 0; i + 1 < records.size(); i ++ ){
            auto a = records[i], b = records[i + 1];
            if (a.state == "on-line" && b.state == "off-line"){
                if (!total) printf("%s %02d\n", name.c_str(), month);
                cout << a.format_time << ' ' << b.format_time;

                double c = sum[b.minutes] - sum[a.minutes];
                printf(" %d $%.2lf\n", b.minutes - a.minutes, c);
                total += c;
            }
        }

        if (total) printf("Total amount: $%.2lf\n", total);
    }

    return 0;
}

1060 Are They Equal

解析

1. 转成浮点数

2.对比转换后 是否相同

注意点

  • 数字不一定标准,可能有前导 00。(一般有个点不过就是这个问题)
  • 如果数值是0,则指数规定为0。

此题用了很多string函数

find( )  找到小数点的位置,从0开始计数, -1代表没有这个字符

#include <iostream>
#include <cstring>

using namespace std;

string change(string a, int n){
    int k = a.find(".");// 找到小数点的位置,从0开始计数
    if (k == -1){ // 如果字符串中没有 ".",在末尾给它加上一位 "." ,k=-1就是没有
        a += '.';
        k = a.find(".");
    } 

    string s = a.substr(0, k) + a.substr(k + 1); // 去除 ".",做成一个新的字符串s
    while (s.size() && s[0] == '0'){// 去除前导0
        s = s.substr(1);            //如果数值是0则字符串会变为空
        k--;
    }

    if (s.empty()) k = 0; // 如果字符串为空 代表s="0",特殊处理一下

    if (s.size() > n) s = s.substr(0, n); // 字符串长度比要求保留的位数要多, 则进行截取操作
    else s += string(n - s.size(), '0'); // 否则 在末尾补0
    
    return "0." + s + "*10^" + to_string(k);
}

int main(){
    int n;
    string a, b;
    cin >> n >> a >> b;

    a = change(a, n);
    b = change(b, n);

    if (a == b) cout << "YES " << a << endl;
    else cout << "NO " << a << ' ' << b << endl;

    return 0;
}

1073 Scientific Notation

解析

从E分割出尾数和阶码

注意点

#include <iostream>

using namespace std;

int main(){
    string s;
    cin >> s;

    if (s[0] == '-') cout << '-';

    int k = s.find("E");

    string a = s[1] + s.substr(3, k - 3); // +1.23400E-03 中 取出 123400
    int b = stoi(s.substr(k + 1));  //取出阶码
    b ++ ;  //小数点向左移动一位,缩小十倍,b++

    if (b <= 0) a = "0." + string(-b, '0') + a; // +1.23400E-03 -> 0.00 123400
    else if (b >= a.size()) a += string(b - a.size(), '0'); // -1.2E+10 -> -12 000 000 000
    else a = a.substr(0, b) + '.' + a.substr(b); // +1.234E2 -> 123.4

    cout << a << endl;

    return 0;
}

1077 Kuchiguse

单词:

suffix 后缀

注意点

#include <iostream>

using namespace std;

const int N = 110;

int n;
string s[N];

int main(){
    cin >> n;
//    把回车读取, 再读取每一行
    getchar();
    for (int i = 0; i < n; i ++) getline(cin, s[i]);

//    后缀长度为 1
//    后缀长度为 2
//    ... 直到sf.size() == s[0].size() 暴力枚举每一种可能的公共后缀
    for (int k = s[0].size(); k > 0; k --){
        string sf = s[0].substr(s[0].size() - k);  //后缀
        bool is_matched = true;

        for (int i = 1; i < n; i ++ )   //枚举剩下字符串
            if (k > s[i].size() || s[i].substr(s[i].size() - k) != sf){
                is_matched = false;
                break;
            }

        if (is_matched){
            cout << sf << endl;
            return 0;
        }
    }

    puts("nai");

    return 0;
}

1082 Read Number in Chinese

解析

将单位和数字分开处理
1. 将数字的单位按每4位数来划分:[个十百千] + 万/亿
2. 如果当前数字 > 0 且上一位数字为 0 则输出ling(仅考虑组内0的个数)
3. 如果[个十百千]中全为0,万位不用输出 100000000 yi Yi

注意点

#include <iostream>
#include <string>
using namespace std;

string Dict[] = { "Ge", "Shi", "Bai", "Qian", "Wan", "Yi" };
string Num[] = { "ling","yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };

string converNum(string str) {
    string ans;
    if (str[0] == '0') {
        return "ling";
    }

    if (str[0] == '-') {
        ans = "Fu ";
        str.erase(0, 1);
    }

    int len = str.length();
    int i = 0;
    while (len) {
        int zeroCnt = 0; //计算每4位数中0个数量,如果有4个0则不用输出万
        bool zero = false; //修改的地方,只考虑组内是否出现0
        for (int j = (len - 1) % 4; j >= 0; j--) { // 枚举个十百千
            //获取最高位的数字
            int pos = str.length() - len;
            int num = str[pos] - '0';

            if (num > 0) { 
                if (zero) {  //如果上一位是0
                    ans += "ling ";  
                    zero = false; 
                } 
                //输出数字+单位
                ans += Num[num] + ' ';
                if (j != 0) ans += Dict[j] + ' ';
            }
            else { //如果当前数字为0
                zeroCnt++;
                zero = true;
            }
            len--;
        }
        //位数大于4位,且该段不全为0,输出亿或者万 
        if (len / 4 > 0  && zeroCnt != 4) ans += Dict[3 + len / 4] + ' ';
    }
    ans.pop_back();
    return ans;
}

int main() {
    string str;
    getline(cin, str);

    str = converNum(str);

    cout << str << endl;
    
    return 0;
}

1084 Broken Keyboard

单词:

case insensitive 不区分大小写

解析

双指针

注意点

#include<iostream>

using namespace std;

int main()
{
    string a,b;
    cin >> a >> b;

    bool st[200] = {0};  //ASCII 0-127   标记字母有没有输出过
    b += '#'; //防止第二行提前扫描完,出现越界,在第二行末尾加一个没出现过的字符 
    for(int i = 0, j = 0; i < a.size(); i++){
        char x = toupper(a[i]), y = toupper(b[j]);
        if(x == y) j++;
        else{
            if(!st[x]) cout << x, st[x] = true;
        }
    }
    return 0;
}

1108 Finding Average

单词:

accurate up to no more than 2 decimal places    精确到不超过小数点后2位

注意点

try catch....

#include <iostream>

using namespace std;

int main(){
    int n;

    cin >> n;

    int cnt = 0; // 合法数字个数
    double sum = 0;   // 合法数字总和

    while (n -- ){
        
        string num;
        cin >> num;
        double x;
        /*
        不加try catch报错terminate called after throwing an instance of 'std::invalid_argument' 
        what():  stof(若传入不可转化为浮点型的字符串)会抛出异常
        */
        bool success = true;
        try{
            size_t idx;   // size type 用来记录大小的数据类型
            x = stof(num, &idx);  // 字符串转换为float型
            // stof判断"5.2abc"这类字符串时视"5.2"为合法,"abc"不合法,但实际上5.2abc不合法
            if (idx < num.size()) success = false;  // 经stof处理后变短的字符串不合法
        }
        catch(...){   // 捕捉所有类型的异常 
            success = false;   // 所有不合法的输入数字都设为error
        }

        if (x < -1000 || x > 1000) success = false; 
        int k = num.find('.');
        if (k != -1 && num.size() - k > 3) success = false;  // 不超过2个小数位(最后一位是num.size()-1)

        if (success) cnt ++, sum += x;
        else printf("ERROR: %s is not a legal number\n", num.c_str());
    }

    if (cnt > 1) printf("The average of %d numbers is %.2lf\n", cnt, sum / cnt);
    else if (cnt == 1) printf("The average of 1 number is %.2lf\n", sum);
    else puts("The average of 0 numbers is Undefined");

    return 0;
}

1124 Raffle for Weibo Followers

#include <iostream>
#include <cstring>
#include <unordered_set>

using namespace std;

const int N = 1010;

int m, n, s;
string name[N];

int main(){
    cin >> m >> n >> s;
    for (int i = 1; i <= m; i ++ ) cin >> name[i];

    unordered_set<string> hash;   //记录发奖人的名字
    int k = s;
    while (k <= m){
        if (hash.count(name[k])) k ++ ;
        else{
            cout << name[k] << endl;
            hash.insert(name[k]);
            k += n;
        }
    }

    if (hash.empty()) puts("Keep going...");

    return 0;
}

1141 PAT Ranking of Institutions

#include <iostream>
#include <cstring>
#include <unordered_map>
#include <vector>
#include <algorithm>

using namespace std;

struct School{
    string name;
    int cnt;
    double sum;

    School(): cnt(0), sum(0) {}   //默认构造函数,哈希表里若某个结构体不存在,创造结构体时会调用默认构造函数
                                  // 

    bool operator< (const School &t) const{
        if (sum != t.sum) return sum > t.sum;
        if (cnt != t.cnt) return cnt < t.cnt;
        return name < t.name;
    }
};

int main(){
    int n;
    cin >> n;

    unordered_map<string, School> hash;
    while (n -- ){
        string id, sch;
        double grade;
        cin >> id >> grade >> sch;

        for (auto& c : sch) c = tolower(c);

        if (id[0] == 'B') grade /= 1.5;
        else if (id[0] == 'T') grade *= 1.5;

        hash[sch].sum += grade;
        hash[sch].cnt ++ ;
        hash[sch].name = sch;
    }

    vector<School> schools;
    for (auto item : hash){
        item.second.sum = (int)(item.second.sum + 1e-8); 
        schools.push_back(item.second);
    }

    sort(schools.begin(), schools.end());
    cout << schools.size() << endl;

    int rank = 1;
    for (int i = 0; i < schools.size(); i ++ ){
        auto s = schools[i];
        if (i && s.sum != schools[i - 1].sum) rank = i + 1;
        printf("%d %s %d %d\n", rank, s.name.c_str(), (int)s.sum, s.cnt);
    }

    return 0;
}

1153 Decode Registration Card of PAT

#include <iostream>
#include <cstring>
#include <unordered_map>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 10010;

int n, m;
struct Person{
 
    string id;
    int grade;

    bool operator< (const Person &t) const
    {
        if (grade != t.grade) return grade > t.grade;
        return id < t.id;
    }
}p[N];

int main(){
    cin >> n >> m;
    for (int i = 0; i < n; i ++ ) cin >> p[i].id >> p[i].grade;

    for (int k = 1; k <= m; k ++ ){
        string t, c;
        cin >> t >> c;

        printf("Case %d: %s %s\n", k, t.c_str(), c.c_str());
        if (t == "1"){
            vector<Person> persons;
            for (int i = 0; i < n; i ++ )
                if (p[i].id[0] == c[0])
                    persons.push_back(p[i]);

            sort(persons.begin(), persons.end());

            if (persons.empty()) puts("NA");
            else
                for (auto person : persons) printf("%s %d\n", person.id.c_str(), person.grade);
        }
        else if (t == "2"){
            int cnt = 0, sum = 0;
            for (int i = 0; i < n; i ++ )
                if (p[i].id.substr(1, 3) == c){
                    cnt ++ ;
                    sum += p[i].grade;
                }

            if (!cnt) puts("NA");
            else printf("%d %d\n", cnt, sum);
        }
        else{
            unordered_map<string, int> hash;
            for (int i = 0; i < n; i ++ )
                if (p[i].id.substr(4, 6) == c)
                    hash[p[i].id.substr(1, 3)] ++ ;

            vector<pair<int, string>> rooms;
            for (auto item : hash) rooms.push_back({-item.second, item.first});

            sort(rooms.begin(), rooms.end());
            if (rooms.empty()) puts("NA");
            else
                for (auto room : rooms)
                    printf("%s %d\n", room.second.c_str(), -room.first);
        }
    }

    return 0;
}

  • 22
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值