pat甲级 第一章 字符串1-10 自用

1字符串6 1534. 字符串减法

//1534. 字符串减法
//
//给定两个字符串 S1 和 S2,S = S1−S2 定义为将 S1 中包含的所有在 S2 中出现过的字符删除后得到的字符串。
//
//你的任务就是计算 S1−S2。
//
//输入格式
//共两行,第一行包含字符串 S1,第二行包含字符串 S2。
//
//输出格式
//输出共一行,表示 S1−S2 的结果。
//
//数据范围
//两个给定字符串的长度都不超过 104。
//
//输入样例:
//They are students.
//aeiou
//输出样例:
//Thy r stdnts.

法一:暴力
//#include<iostream>
//#include<string>
//using namespace std;
//int main() {
//	string a, b, c="";
//	getline(cin, a);
//	getline(cin, b);
//	bool flag = true;
//	for (int i = 0; i < a.size() ; i++) {		
//		for (int j = 0; j < b.size() ; j++) {
//			if (a[i] == b[j]) {
//				flag = false;
//				break;
//			}
//		}
//		if (flag == true) {
//			c = c + a[i];
//		}
//		flag = true;
//	}
//	cout << c << endl;
//}


//法二:利用hash表将第二个for循环变成o(1)
#include <iostream>;
#include <unordered_set>;
#include <string>
using namespace std;
string s1, s2;
int main()
{
    getline(cin, s1);
    getline(cin, s2);
    unordered_set<char> hash;  // 定义哈希表
    for (auto c : s2) hash.insert(c);  // 将s2中的字符插入哈希表

    string res;
    for (auto c : s1)
        if (!hash.count(c))//if(hash.count(c)==0)  就是没找到c的时候
            res += c;

    cout << res << endl;

    return 0;
}

//hash.count(c)是统计哈希表中c出现的次数,0代表没出现,2代表出现2次
//hash.find(c)找到了是返回迭代器
//hash的操作比如 cout都是o(1)级别

 

 

1字符串7 1557. 说话方式

//1557. 说话方式
//不同的人对描述同一种事物的同义词的偏爱程度可能不同。
//
//例如,在说警察时,有人喜欢用 the police,有人喜欢用 the cops。
//
//分析说话方式有助于确定说话者的身份,这在验证诸如和你线上聊天的是否是同一个人十分有用。
//
//现在,给定一段从某人讲话中提取的文字,你能确定他的最常用词吗?
//
//输入格式
//输入共一行,包含一个字符串,以回车符 \n 终止。
//
//输出格式
//共一行,输出最常用词以及其出现次数。
//
//如果常用词有多个,则输出字典序最小的那个单词。
//
//注意,单词在输出时,必须全部小写。
//
//单词是指由连续的字母和数字构成的,被非字母数字字符或行首 / 行尾分隔开的,连续序列。
//
//单词不区分大小写。
//
//数据范围
//输入字符串长度不超过 1048576,且至少包含一个大小写字母或数字。
//
//输入样例:
//Can1 : "Can a can can a can?  It can!"
//输出样例:
//can 5
#include <iostream>
#include <unordered_map>
#include <string>
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> hash;

    for (int i = 0; i < str.size(); i++)
        if (check(str[i]))
        {
            string word;
            int j = i;
            //当j没有走到边界,且str[j]是个单词字母时,word后面就加上str[j]这个字母
            //to_lower变成小写
            while (j < str.size() && check(str[j])) {
                word += to_lower(str[j++]);
            }
            //hash表里该单词个数+1
            hash[word] ++;
            i = j;
        }

    //出现次数最多的单词赋给word,
    //以及出现次数相同,但是字典序更小的单词,赋值给word,最后输出word,就是出现次数最多的单词
    string word;
    int cnt = -1;
    //遍历hash表
    for (auto item : hash) {
        //item.first是单词,item.second是出现次数
        if (item.second > cnt || item.second == cnt && item.first < word)
        {
            word = item.first;
            cnt = item.second;
        }
    }
    cout << word << ' ' << cnt << endl;
    return 0;
}

 

 

1字符串8 1547. 约会

大侦探福尔摩斯接到一张奇怪的字条:我们约会吧!3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm

大侦探很快就明白了,字条上奇怪的乱码实际上就是约会的时间星期四 14:04,因为前面两字符串中第 11 对相同的大写英文字母(大小写有区分)是第 44 个字母 D,代表星期四;第 22 对相同的字符是 EE ,那是第 55 个英文字母,代表一天里的第 1414 个钟头(于是一天的 00 点到 2323 点由数字 00 到 99、以及大写字母 AA 到 NN 表示);后面两字符串第 11 对相同的英文字母 ss 出现在第 44 个位置(从 00 开始计数)上,代表第 44 分钟。

现给定两对字符串,请帮助福尔摩斯解码得到约会的时间。

补充

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

输入格式

输入在 44 行中分别给出 44 个非空、不包含空格、且长度不超过 6060 的字符串。

输出格式

在一行中输出约会的时间,格式为 DAY HH:MM,其中 DAY 是某星期的 33 字符缩写,即 MON 表示星期一,TUE 表示星期二,WED 表示星期三,THU 表示星期四,FRI 表示星期五,SAT 表示星期六,SUN 表示星期日。

题目输入保证每个测试存在唯一解。

输入样例:

3485djDkxh4hhGE 
2984akDfkkkkggEdsb 
s&hgsfdk 
d&Hyscvnm

输出样例:

THU 14:04
#include <cstdio>//题目要求保留5位小数,所以用scanf,printf,要include<cstdio>
#include <iostream>
using namespace std;
int main()
{
    //读入4个字符串
    string a, b, c, d;
    cin >> a >> b >> c >> d;

    int k = 0;
    //一定有解,所以while(true)
    while (true)
    {
        //找到前俩字符串相同的字母,并且要在A-G之间,没找到就k++往后找
        //这个while循环结束后,a[k]=b[k]就是星期几
        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++;
    while (true)
    {
        if (a[k] == b[k] && (a[k] >= '0' && a[k] <= '9' || a[k] >= 'A' && a[k] <= 'N')) break;
        k++;
    }

    //%d是整型输出格式。02的意思是如果输出的整型数不足两位,左侧用0补齐。
    /*1、%d就是普通的输出了
    2、 % 2d是将数字按宽度为2,采用右对齐方式输出,若数据位数不到2位,则左边补空格。如下:
    3、 % 02d,和 % 2d差不多,只不过左边补0
    4、 % .2d从执行效果来看,和 % 02d一样*/

    //输出前俩字符串中,第二个相等的字符所代表的小时,A代表10,N代表24,所以要+10
    printf("%02d:", a[k] <= '9' ? a[k] - '0' : a[k] - 'A' + 10);


    //找后俩字符串c,d中相等的字符,出现在位置i,则代表i分钟
    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;
}

//总结:
//printf("%02d\n", i);
//
//char weekdays[7][4] = { "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };
//printf("%s ", weekdays[a[k] - 'A']);

 

1字符串9 1493. 电话账单

话公司按以下规则向客户收费:

拨打长途电话每分钟要花费一定的费用,具体收费取决于拨打电话的时间。

客户开始拨打长途电话的时间将被记录,客户挂断电话的时间也将被记录。

每个月都要给客户发送一次话费账单,账单中应包含每次通话记录以及相关收费等信息。

给定一组电话记录,你的工作是为客户准备帐单。

输入格式

输入包含两部分:费率结构和电话记录。

费率结构由一行组成,该行包含24个非负整数,分别表示从 00:00-01:00 的收费(分/分钟),从 01:00-02:00 的收费,以此类推…

下一行包含一个正整数 NN。

接下来 NN 行,每行包含一条记录。

每个记录由客户名称(最多 2020 个字符的字符串,不带空格),时间和日期(mm:dd:hh:mm)以及单词 on-line 或 off-line 组成。

所有日期都在同一个月内,每个 on-line 记录都与按时间顺序排列的同一位客户的下一条记录配对,但前提是这条记录是 off-line

所有未与 off-line 记录配对的 on-line 记录以及未与 on-line 记录配对的 off-line 记录都必须忽略。

输入中至少包含一个成功的配对。

同一客户在同一时间不会有两个或以上的电话记录。

使用 2424 小时制记录时间。

输出格式

你需要为每个客户打印电话费。

账单必须按照客户姓名的字母顺序(按ASCII码顺序,大写字母在前,小写字母在后)打印。

对于每个客户,首先以示例显示的格式在一行中打印客户名称和帐单月份。

然后,对于每个通话时间段,在一行中分别打印开始和结束时间和日期(dd:hh:mm),持续时间(以分钟为单位)和通话费用。

通话必须按时间顺序列出。

最后,以示例显示的格式打印该月的总费用。

注意,没有任何有效通话记录的客户直接忽略,不予打印账单。

数据范围

1≤N≤10001≤N≤1000

输入样例:

10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
10
CYLL 01:01:06:01 on-line
CYLL 01:28:16:05 off-line
CYJJ 01:01:07:00 off-line
CYLL 01:01:08:03 off-line
CYJJ 01:01:05:59 on-line
aaa 01:01:01:03 on-line
aaa 01:02:00:01 on-line
CYLL 01:28:15:41 on-line
aaa 01:05:02:24 on-line
aaa 01:04:23:59 off-line

输出样例:

CYJJ 01
01:05:59 01:07:00 61 $12.10
Total amount: $12.10
CYLL 01
01:06:01 01:08:03 122 $24.40
28:15:41 28:16:05 24 $3.85
Total amount: $28.25
aaa 01
02:00:01 04:23:59 4318 $638.80
Total amount: $638.80

 

 

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

using namespace std;
const int N = 1010, M = 31 * 1440 + 10;//一天有1440分钟

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

struct Record
{
    int minutes;//记录该时间有多少分钟,比如1点20 是80分钟
    string state;//记录offline online 这些状态
    string format_time;//记录标准时间

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

bool cmp(Record r1,Record r2) {
    return r1.minutes < r2.minutes;
}

map<string, vector<Record>> persons;

int main()
{
    //输入0:00-0:59,1:00-1:59,,,23:00-23:59这二十四个区间段,每分钟收费多少美分
    for (int i = 0; i < 24; i++) cin >> cost[i];
    //利用了前缀和思想,sum[1]代表第一分钟的花费,sum[2]代表这两分钟的花费
    //sun[100]代表这100分钟的花费
    //后面是i-1,自己带个数字进去试试,比如第六十分钟,i-1=59,(i - 1) % 1440 / 60=0,
    //还是属于cost[0]这个时间段的花费
    //最后除以100是将美分变成美元
    for (int i = 1; i < M; i++) sum[i] = sum[i - 1] + cost[(i - 1) % 1440 / 60] / 100.0;

    //输入n条记录
    cin >> n;
    char name[25], state[10], format_time[20];
    int month, day, hour, minute;
    for (int i = 0; i < n; i++)
    {
        //输入格式复杂所以用scanf
        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 });
    }

    //字典序遍历每一个同学,map遍历天然字典序
    //加个& 就不会涉及到复制(一个副本),代码会快一些
    //遍历,一次取出一个person,包含该人的所有通化记录
    for (auto& person : persons)

    {
        //map<string, vector<Record>> persons;
        //first 就是 这个string,second 就是这个vector<Record>
        //string name = person.first;
        auto name = person.first;

        //records 就是map里面的vector<Record>,vector里面放了一堆record
        //vector<Record> records = person.second;
        auto records = person.second;
        

        //yxc的sort
        //sort(records.begin(), records.end());

        //而我用cmp函数一样
        sort(records.begin(), records.end(),cmp);

        //total是1次或者多次通化下来,总花费的金额
        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")
            {
                //如果total==0,说明是第一次输出该同学信息:姓名和月份
                //用%s输出name 时候 要用到 .c_str(),返回string首地址的指针才行
                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)等价于if(total!=0)
        if (total) printf("Total amount: $%.2lf\n", total);
    }
    return 0;
}

1494. 银行排队

 

 

假设一家银行有 KK 个服务窗口。

窗户前面有一条黄线,将等候区分为两部分。

所有客户都必须在黄线后面排队等候,直到轮到他/她服务并且有可用的窗口为止。

假定一个窗口不能被单个客户占用超过 11 小时,即如果某位顾客的业务已经办理了一小时,则立即终止此项业务。

现在给定每个客户的到达时间 TT 和业务办理时间 PP,请计算所有客户的平均等待时间。

输入格式

第一行包含两个整数 NN 和 KK,分别表示客户数量以及窗口数量。

接下来 NN 行,每行包含两个时间,分别是一个客户的到达时间,用 HH:MM:SS 表示,以及一个客户的业务办理时间 PP(单位:分钟)。

HH 在 [00,23][00,23] 范围内,MM 和 SS 都在 [00,59][00,59] 范围内。

所有客户的到达时间均不相同。

请注意,银行的营业时间为 08:00 至 17:00

任何人提前到达都必须排队等候至 08:00,而任何人来得太晚(在 17:00:01 或之后到达)都将不被服务也无需计入平均值。

注意只要客户在17:00之前排上队,则即使办理业务时超过17:00,也会被服务。

输出格式

输出平均等待时间(单位:分钟),结果保留一位小数。

注意,从到达银行至开始办理业务这一期间视为等待期间。

数据范围

1≤N≤1041≤N≤104,
1≤K≤1001≤K≤100

输入样例:

7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10

输出样例:

8.2
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 10010, M = 110;
int n, m;

struct Person
{
    int arrive_time;
    int service_time;
    // 对结构体排序,就要在结构体里重载运算符!!!
    bool operator< (const Person& t) const  // 按到达时间排序
    {
        return arrive_time < t.arrive_time;
    }
}persons[N];

bool cmp(Person p1,Person p2) {
    return p1.arrive_time < p2.arrive_time;
}

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

    for (int i = 0; i < n; i++)
    {
        int hour, minute, second, service_time;
        scanf("%d:%d:%d %d", &hour, &minute, &second, &service_time);

        // 服务时间不得超过60min:已经办理了一小时,则立即终止此项业务
        service_time = min(service_time, 60);

        //定义结构体时直接赋值,结构体={第一个参数,第二个参数}
        persons[i] = { hour * 3600 + minute * 60 + second, service_time * 60 };
    }

    priority_queue<int, vector<int>, greater<int>> windows;

    // 初始化窗口,从早八点开始
    for (int i = 0; i < m; i++) windows.push(8 * 3600);  // 先把m个窗口安排好


    // 对人来的顺序进行排序
    sort(persons, persons + n);

    //总共等待时间,和被服务的人数(有些人来晚了忽略)
    int sum = 0, cnt = 0;

    for (int i = 0; i < n; i++)
    {
        auto person = persons[i];
        int w = windows.top();
        windows.pop();
        if (person.arrive_time > 17 * 3600) break;  // 来晚了,则忽略

        int start_time = max(person.arrive_time, w);
        sum += start_time - person.arrive_time;
        cnt++;

        windows.push(start_time + person.service_time);
    }

    printf("%.1lf\n", (double)sum / cnt / 60);

    return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值