字符串处理类型

y总讲解

1473. A + B 格式

计算 a+b 并以标准格式输出总和----也就是说,从最低位开始每隔三位数加进一个逗号(千位分隔符),如果结果少于四位则不需添加。

输入格式
共一行,包含两个整数 a 和 b。

输出格式
共一行,以标准格式输出 a+b 的和。

数据范围
−106≤a,b≤106
输入样例:
-1000000 9
输出样例:
-999,991
分析
尽可能用to_string( c )
不然负数和0都要考虑

string num=to_string(c);
//等同于
int d=abs(c);
//while(d) num+=char(d%10+'0'),d/=10; //123会得到321,修改一下
while(d) num=char(d%10+'0')+num,d/=10;  //把新元素放到前面去
if(c<0)num='-'+num;
if(!c)num="0";
#include<iostream>
using namespace std;

int main(){
	int a , b;
	cin >> a >> b;
	int c=a+b;
	string num=to_string(c);  //可以把一个数字(不管整形还是浮点数都算)转换成字符串
	string res;
	
	for(int i=num.size()-1,cnt=0 ; i>=0 ; i--){
		res=num[i]+res;                         //是在字符串前面加字符 
		++cnt;
		if(cnt%3==0 && i && num[i-1]!='-')  //前面没有数字 : 不能为0位 、 前面不是负号
		{
			res=','+res;
		}
	} 
	cout<<res<<endl;
	
	return 0; 
} 

1477. 拼写正确

给定一个非负整数 N,你的任务是计算 N 的所有数字的总和,并以英语输出总和的每个数字。

输入格式
共一行,包含一个整数 N。

输出格式
共一行,用英语输出总和的每个数字,单词之间用空格隔开。

数据范围
0≤N≤10100
输入样例:
12345
输出样例:
one five
分析:
1.用char二维数组存数
2.为了末尾没有空格,通常都是先输出第一个,然后再空格+值遍历输出

#include<iostream>
using namespace std;
int main(){
	string n;
	cin>>n;
	
	int s=0;
	for(auto c : n){  //计算每一位总和 
		s+=c-'0';
	}
	string str=to_string(s);
	
	//先用一个字符数组写下来
	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;
} 

1478. 签到与签出

每天第一个到机房的人负责开门,最后一个从机房离开的人负责锁门。

现在,给定每个人的签到与签出记录,请你找出当天开门的人以及锁门的人分别是谁。

输入格式
第一行包含整数 M,表示共有 M 个人的签到签出记录。

接下来 M 行,每行的形式如下:

ID_number Sign_in_time Sign_out_time
时间以 HH:MM:SS 形式给出,ID_number 是一个长度不超过 15 的字符串。

输出格式
共一行,输出开门人和锁门人的ID_number,用一个空格隔开。

数据范围
1≤M≤10,
数据保证每个人的签到时间早于签出时间,并且不会出现两个人同时签到或同时签出的情况。

输入样例:

3
CS301111 15:30:28 17:00:10
SC3021234 08:00:00 11:25:25
CS301133 21:45:00 21:58:40

输出样例:

SC3021234 CS301133

分析:
看输入格式就知道是一个字符串问题

#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的话,就是第一个人,需要直接记录下来 
 		{
			open_id=id;
			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;
} 

1519. 密码

为了准备 PAT,系统不得不为用户生成随机密码。

但是有时一些数字和字母之间总是难以区分,比如 1(数字一)和l(L 的小写),0(数字零)和 O(o 的大写)。

一种解决办法是将1(数字一)替换为@,将 0(数字零)替换为 %,将l(L 的小写)替换为L,将O(o 的大写)替换为 o

现在,你的任务就是帮助系统检查这些用户的密码,并对难以区分的部分加以修改。

输入格式
第一行包含一个整数 N,表示用户数量。

接下来 N 行,每行包含一个用户名和一个密码,都是长度不超过 10 且不含空格的字符串。

输出格式
首先输出一个整数 M,表示已修改的用户密码数量。

接下来 M 行,每行输出一个用户名称和其修改后的密码。

用户的输出顺序和读入顺序必须相同。

如果没有用户的密码被修改,则输出
There are N accounts and no account is modified,其中 N 是用户总数。

如果 N=1,则应该输出 There is 1 account and no account is modified

数据范围
1≤N≤1000
输入样例1:

3
Team000002 Rlsp0dfa
Team000003 perfectpwd
Team000001 R1spOdfa

输出样例1:

2
Team000002 RLsp%dfa
Team000001 R@spodfa

输入样例2:

1
team110 abcdefg332

输出样例2:

There is 1 account and no account is modified

输入样例3:

2
team110 abcdefg222
team220 abcdefg333

输出样例3:

There are 2 accounts and no account is modified

#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)  //如果m等于0,即没有可以修改的
	{
		if(n==1)puts("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;
} 

1520. 男孩 vs 女孩

给定 N 个学生的成绩信息,请你求出女生第一名与男生倒数第一名的分数差距。

输入格式
第一行输入整数 N,表示学生数量。

接下来 N 行,每行包含一个学生的姓名,性别,ID和成绩。其中姓名和ID是长度不超过 10 且不包含空格的字符串。性别为 F(女)或 M(男)。成绩是一个范围在 [0,100] 的整数。保证所有学生的成绩互不相同。

输出格式
输出共三行。

第一行输出女生第一名的姓名和ID。

第二行输出男生倒数第一名的姓名和ID。

第三行输出女生第一名的成绩与男生倒数第一名的成绩的差的绝对值。

如果不存在某个性别的学生,则在对应行输出 Absent

在第三行输出 NA

数据范围
1≤N≤101
输入样例1:

3
Joe M Math990112 89
Mike M CS991301 100
Mary F EE990830 95

输出样例1:

Mary EE990830
Joe Math990112
6

输入样例2:

1
Jean M AA980920 60

输出样例2:

Absent
Jean AA980920
NA

分析:
需要记录:
1.女生第一名的姓名,id,分数(string string int)
2.男生倒数第一名的姓名,id,分数

对于每一个学生 判断一下性别,if是男生,看看是不是比当前男生低,低的话就更新一下。else是女生,看看是不是比当前女生高,高的话就更新一下

输出要判断一下,string是不是空的就可以判断是否存不存在。
if 女生不存在,输出absent。如果存在就输出学号
if 男生不存在,输出absent。如果存在就输出学号
if都存在,则输出他们的差值,否则输出na

#include<iostream>
using namespace std;
int main()
{
	int n;cin>>n;
	
	string girl_name,girl_id;  //女生第一名信息 
	int girl_score;
	string boy_name,boy_id;    //男生第一名信息 
	int boy_score;
	
	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;
			}
		}
		
		if(sex=="M")  //如果是男生 
		{
			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)<<endl;
	else
		cout<<"NA"<<endl;
	
	return 0;
} 

1534. 字符串减法 (hash优化)

给定两个字符串 S1 和 S2,S=S1−S2 定义为将 S1 中包含的所有在 S2 中出现过的字符删除后得到的字符串。

你的任务就是计算 S1−S2。

输入格式
共两行,第一行包含字符串 S1,第二行包含字符串 S2。

输出格式
输出共一行,表示 S1−S2 的结果。

数据范围
两个给定字符串的长度都不超过 104。

输入样例:
They are students.
aeiou
输出样例:
Thy r stdnts.
分析:
时/空限制:0.1s / 64MB,需要优化
S1=“They are student.”
S2=“aeiou”
法一:暴力做法,遍历S1,二重循环判断出没出现过 O(n^2)
超时

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

法二(优化)
把check_exists变成不循环,该函数含义:【判断某个元素是否在某个集合中出现过】。【哈希表】(插入、删除、修改、查找)
遍历是O(n) 转换成 哈希表 就是 O(1)

#include<unordered_set>  //头文件
unordered_set<char> hash; //定义哈希表
hash.insert(c); //插入哈希表
hash.count(c) //统计hash的个数,返回set中元素的个数,由于set的特殊性,所以结果只有0或者1

数据结构&STL(十)——hash_set/unordered_set

#include<iostream>
#include<unordered_set>  //头文件 
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中字符插入到hash表里 O(1)
	
	string res;
	for(auto c:s1){
		if(!hash.count(c)){  //查找某元素有没有出现过 ,返回这个元素在hash表中出现的个数 
			res+=c;           //如果没有出现过的话,就是0 ,如果出现过的话就不是0 
		}                    //hash表有很多种,因为这个是set ,不允许有重复元素 
	}                        //所以在这,出现过就是1 没出现就是0 
	cout<<res<<endl;
	return 0;
} 
#include<unordered_set>
#include<unordered_map>
#include<set>
#include<map>
#include<multiset>
#include<multimap>

//基于平衡树实现,时间复杂度都是O(logn)
//有序
set<int> a;  //维护一个有序集合    不允许有重复元素
map<int,int> b; //维护一个映射 b[x]=y  不允许有重复元素
multiset<int> c;  //允许有重复元素
multimap<int,int> d;   //允许有重复元素
//基于哈希表实现:O(1)
//无序
unordered_set<int> e;
unordered_map<int,int> f;
unordered_multiset<int> g;
unordered_multimap<int,int> h;

1557. 说话方式(can没打印出来)

不同的人对描述同一种事物的同义词的偏爱程度可能不同。

例如,在说警察时,有人喜欢用 the police,有人喜欢用 the cops

分析说话方式有助于确定说话者的身份,这在验证诸如和你线上聊天的是否是同一个人十分有用。

现在,给定一段从某人讲话中提取的文字,你能确定他的最常用词吗?

输入格式
输入共一行,包含一个字符串,以回车符 \n 终止。

输出格式
共一行,输出最常用词以及其出现次数。

如果常用词有多个,则输出字典序最小的那个单词。

注意,单词在输出时,必须全部小写。

单词是指由连续的字母和数字构成的,被非字母数字字符或行首/行尾分隔开的,连续序列。

单词不区分大小写。

数据范围
输入字符串长度不超过 1048576,且至少包含一个大小写字母或数字。

输入样例:
Can1: "Can a can can a can? It can!"
输出样例:
can 5
分析:
1.单词不区分大小写,都说输出要全部小写。所以先转换一下
2.如果有多个出现次数一样多,输出字典序最小的
步骤:
1.读入一整行:getline(cin,str)
2.提取每个单词【双指针算法】

for(int i = 0;i<str.size();i++)  //遍历整个字符串
	if 是字母或数字
		j=i 
		while(j<str.size() && j 也是字母或数字)j++; 

3.把单词存到哈希表里
找完一个单词之后,让i直接跳过去,i=j,

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

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;
			while(j<str.size() && check(str[j]))  //没有走到边界   满足check 
				word += tolower(str[j++]);  //65A  97a
			hash[word]++; 
			i=j;
		}
	}
	//存答案 
	string word;
	int cnt=-1;
	for(auto item : hash)
	{
		if(item.second > cnt || item.second == cnt && item.first < word) //字典序小于单词 
		{
			word = item.first;
			cnt = item.second;
		}
	}
	cout<< word <<' '<< cnt <<endl;
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DDouble-

你的鼓励是我最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值