PAT (Advanced Level) Practice
【1112】map、字符串处理
【1121】map、set(find\insert\erase)
【1124】map简单()
【1149】 map、STL、int exist[100000] = {0}判断ID是否存在
【1100】 map、STL、getchar()、getline()、cin
【1071】map、isalnum()cctype判断是否是数字和大小写字母()
【1054】map 简单
【1022】map.find(), vector
set:
【1063】 Set Similarity (25) [集合set,STL的使⽤]
【1120】 Friend Numbers (20) [set的应⽤]
【1121】 Damn Single (25) [set的应⽤]
【1129】 Recommendation System (25) [set的应⽤,运算符重载]
【1154】Vertex Coloring (25) [set,hash]
题目大意:键盘某些键卡住了,按⼀次重复k次,要求找出可能的键,并且输出正确的字符串顺序。可能的键要求按照被发现的顺序输出。
注意:
(1)认真读题!!!!
(2)如果某个键是坏的,则一定会连续输出k的整数倍次数
因此,如果有一个字符连续输出k的整数倍次,可以置might_bad为true
但是,如果有一个字符连续输出不是k的整数倍,则一定不是坏键,sure_not_bad为true
要在might_bad中找到sure_not_bad为true的,更新
(3)可以像遍历数组一样遍历字符串: for(int i=1; i
#include
#include
#include
#include
using namespace std;
int main(){
int k;
string data;
scanf("%d", &k);
cin>>data;
map<char, bool> might_bad; // 所有连续计数为k的字符都可能时坏的
map<char, bool> sure_not_bad; // 但如果当前出现的次数确定小于k,则无论之后是否出现k个连续,都不是坏键
unordered_set<char> bad_key;
int pre = data[0];
int cnt = 1;
for(int i=1; i<data.length(); i++){
if(data[i] == pre) cnt++;
else{ // 如果前后两个字符不相等,且pre字符的计数cnt不能整除k,则pre一定不是坏键
if(cnt%k!=0) sure_not_bad[pre] = true; // 这里比如k=3,但如果连续出现5个a,则a不是坏键,因为若是坏则一定是3的整数倍
cnt = 1;
}
might_bad[data[i]] = ((cnt%k)==0);
pre = data[i];
}
// 从可能是坏键中排除确定不是坏的
for(int i=0; i<data.length(); i++){
if(sure_not_bad[data[i]]) might_bad[data[i]] = false;
}
// 输出坏键,set保证每个只输出一次
for(int i=0; i<data.length(); i++){
if(might_bad[data[i]]){
if(bad_key.find(data[i])==bad_key.end()){
cout<<data[i];
}
bad_key.insert(data[i]);
}
}
cout<<endl;
// 输出坏键修复后的字符串
for(int i=0; i<data.length(); ){
cout<<data[i];
if(!might_bad[data[i]]){
i++;
}else{
i += k;
}
}
return 0;
}
1121 Damn Single (25 分)
给出couple的信息,在party中couple成对出现则认为不是单身狗,否则认为是单身狗;找出所有单身狗的人。
party中的人保存在set中,couple保存成map,遍历map,若两个人都在set中,则从set中erase。最终set的大小为所有单身狗的数目。
#include
#include
#include
using namespace std;
int main(){
// 输入couple信息,保存在映射map中
map<int, int> couple;
set<int> party;
int N, M, c1, c2, p1;
cin>>N;
while(N--){
scanf("%d %d", &c1, &c2);
couple[c1] = c2;
}
// 输入参加party的人的信息,保存在set中
cin>>M;
for(int i=0; i<M; i++){
scanf("%d", &p1);
party.insert(p1);
}
// 遍历map,若key和value同时出现在set中,则从set中删除两个人(不是单身狗)
for(auto it = couple.begin(); it!=couple.end(); it++){
if((party.find(it->first)!=party.end()) && (party.find(it->second)!=party.end())){
party.erase(it->first);
party.erase(it->second);
}
}
// 遍历输出set中的元素
cout<<party.size()<<endl;
int num = 0;
for(auto iter=party.begin(); iter!=party.end(); iter++){
num++;
printf("%05d%s", *iter, num==party.size()?"\n":" ");
}
}
1149 Dangerous Goods Packaging
思路:
首先先将所有无法共存的id,存放在incompatible map映射中,是int到vector的映射;
接着输入所有需要判断的新的id,存入exist_id中;
并且维持一个exist的判断数组,对于新输入的id,exist[id]置为1,否则置为0;
遍历所有incompatible中的映射,若存在于exist,则无法共存,判断compatible为false;
#include
#include
#include
using namespace std;
int main(){
int N, M;
cin>>N>>M;
int a,b;
map<int, vector<int>> incompatible; // 无法一起存放的物质,存放在map中
for(int i=0; i<N; i++){
scanf("%d %d",&a,&b);
incompatible[a].push_back(b);
incompatible[b].push_back(a);
}
while(M--){
int K, id;
bool compatible = true;
int exist[100000] = {0}; // 存在的id,若存在则置为1
cin>>K;
vector<int> exist_id(K);
for(int i=0; i<K; i++){
scanf("%d",&id);
exist_id[i] = id;
exist[id] = 1;
}
// 遍历所有无法共存的id映射,若同时存在于exist_id,则表示无法共存,compatible置为false
for(int i=0; i<exist_id.size(); i++){
for(int j=0; j<incompatible[exist_id[i]].size(); j++){
int id1 = exist_id[i];
int id2 = incompatible[exist_id[i]][j];
if(exist[id1] && exist[id2]){
compatible = false;
break;
}
}
}
printf("%s\n",compatible==true ? "Yes":"No");
}
return 0;
}
1124 Raffle for Weibo Followers (20 分)
map:用于映射已经是winner的人名和被选中的次数
#include
#include
using namespace std;
unordered_map<string, int> winner; // 用于映射已经是winner的人名和被选中的次数
int main(){
int m, n, s;
scanf("%d %d %d", &m, &n, &s);
string w;
bool has_winner = false;
for(int i=1; i<=m; i++){
cin>>w;
if(winner[w]==1) s = s + 1; // 如果这个人已经被选中了,则consider the next one
if(i==s && winner[w]!=1){ // 注意n是跳过的人数,因此下面要s=s+n
cout<<w<<endl;
s = s + n;
winner[w]++;
has_winner = true;
}
}
if(!has_winner) cout<<"Keep going..."<<endl;
return 0;
}
1100 Mars Numbers (20 分)
Mars计数方式和Earth计数方式转换
读取数据:
getchar() 可用于读取字符,用于读取多余的’\n’
对于代码
char test1 = getchar();
char test2 = getchar();
此时在控制台中输入字符“a”并且按下回车键,test1的值是字符“a”,而test2的值是“\n”
getline() 函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中
当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格、制表符或换行符)。一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取
cin可以输入 “Mark” 或 “Twain”,但不能输入 “Mark Twain”,因为cin不能输入包含嵌入空格的字符串。
#include
#include
#include
using namespace std;
string etm1[13] = {"tret","jan", "feb", "mar", "apr", "may", "jun", "jly", "aug", "sep", "oct", "nov", "dec"};
string etm2[13] = {"NONE","tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mer", "jou"};
bool is_mars(string s){
return (s[0]-'0' >=49);
}
void to_earth(string s){
int t1 = 0, t2 = 0;
string s1 = s.substr(0,3), s2;
if(s.length()>4) s2 = s.substr(4,3);
// if(s1=="tre") s1 = "tret";
// if(s2=="tre") s2 = "tret";
for(int i=1; i<=12; i++){
if(s1==etm1[i] || s2==etm1[i]) t1 = i;
if(s1==etm2[i]) t2 = i;
}
cout<<(t2*13+t1)<<endl;
}
void to_mars(string s){
int pre = stoi(s)/13;
int sec = stoi(s)%13;
if(pre > 0){
cout<<etm2[pre];
if(sec!=0) cout<<" "<<etm1[sec]<<endl;
else cout<<endl;
}else{
cout<<etm1[sec]<<endl;
}
}
int main(){
int N;
string s;
cin>>N;
getchar();
while(N--){
getline(cin, s);
if(is_mars(s)) to_earth(s);
else to_mars(s);
}
return 0;
}
【1054】map 简单
1054 The Dominant Color (20 分)
#include
#include
using namespace std;
int main(){
int M, N, a;
map<int, int> m;
scanf("%d %d", &M, &N);
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
scanf("%d", &a);
m[a]++;
}
}
int max_num = 0;
int dominant = -1;
for(auto it=m.begin(); it!=m.end(); it++){
if(it->second > max_num){
max_num = it->second;
dominant = it->first;
}
}
cout<<dominant<<endl;
}
1022 Digital Library (30 分)
(1)设置数组保存map,map1: title, map2: author, map3: keywords, map4: publisher, map5: year
每个map为string到string_set的映射,具体内容到ID集合的映射
(2)通过getline和while(cin>>k)输入
(3)查询:map也可以通过find判断某个key是否在map中,若key在map中,则遍历key对应的set,输出
#include
#include
#include
#include
#include
using namespace std;
int main(){
string sN, ID, title, author, keywords, publisher, year;
getline(cin, sN);
int N = stoi(sN);
// 设置数组保存map,map1: title, map2: author, map3: keywords, map4: publisher, map5: year
// 每个map为string到string_set的映射,具体内容到ID集合的映射
vector<map<string, set<string>>> vm;
vm.resize(6);
for(int i=0; i<N; i++){
getline(cin, ID);
getline(cin, title);
vm[1][title].insert(ID);
getline(cin, author);
vm[2][author].insert(ID);
// 输入关键词test code debug sort keywords,关键词之间空格间隔,分别读入关键词
// 方法1
while(cin>>keywords){
vm[3][keywords].insert(ID);
char c = getchar();
if(c=='\n') break;
}
/*
// 方法2
getline(cin, keywords);
string t;
int l = keywords.length();
for(int i=0; i
getline(cin, publisher);
vm[4][publisher].insert(ID);
getline(cin, year);
vm[5][year].insert(ID);
}
string sk, t1;
getline(cin, sk);
int k = stoi(sk);
while(k--){
getline(cin, t1);
cout<<t1<<endl; // 1: The Testing Book
// 每行第一个字符为judge
int judge = stoi(t1.substr(0,1));
// 第三个字符之后是具体的map中的key
string t2 = t1.substr(3);
// scanf("%d: ", &num);
// string temp;
// getline(cin, temp);
// cout << num << ": " << temp << "\n";
// map也可以通过find判断某个key是否在map中
// 若key在map中,则遍历key对应的set,输出
if(vm[judge].find(t2) != vm[judge].end()){
for(auto it=vm[judge][t2].begin(); it!=vm[judge][t2].end(); it++)
cout<<*it1<<endl;
}else{
cout<<"Not Found"<<endl;
}
}
return 0;
}