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;
}