map关联容器使用详解

16 篇文章 7 订阅

map关联容器使用详解

咳咳,马上就要期末考试了,说实话有些科目还是有点方的,有些课一直没有听,也没有去练习,然后最近几日还要去赶双创的项目,害。。。。按照流程,今天来讲讲map关联容器的使用,咳咳,冲冲冲。。。

  • 首先哈,来讲一个问题。
  • 有n个学生,然后每个人都有姓名name和学号id,现在给定一个学生的name,要求查找他的id。
  • 那么通常情况下呢,我们会建立一个自定义一个数据结构,里面有name和id两个变量,然后进行储存。

在这里插入图片描述

  • 如此,也能实现数据的存储的查询,但是每次查询的复杂度都是O(n)级别的,效率贼低,这并不能满足我们算法复杂度的需要,那么有什么办法能够更快一点呢。答案还是有的,那就是今天我们要学习的map关联容器。
  • 这玩意算的上是算法里面用的最多的了,反正就是贼好用。
  • map他是一个关联容器,他实现从 到值的 的映射,内部的函数实现是用平衡二叉树实现了,复杂度也是对数极的,效率高。
  • 用map来写第一个问题,那就太简单了,直接起飞。

在这里插入图片描述

  • map的定义呢,里面是两个数据类型,第一个类型表示的是 键key 的类型,第二个类型表示这 值value 的类型。类型可以随意的,你需要映射什么类型就设置什么类型。例如:
#include<bits/stdc++.h>
using namespace std;
int main(){
	map<string , int > a;    //表示字符映射整型。
	a["xiaoming"]=21;			//map容器的输入,表示小明19岁了。
	cout << a["xiaoming"] << endl;  //map容器的输出  ,直接输出小明的岁数
}
  • 好滴,这个输入输出已经会了,那接下来看看map容器的遍历和 键值的引用吧!

在这里插入图片描述

  • 咳咳,可以看出哈! 我们使用 it->first 引用的是 键key ,然后 it->second 引用的是 值value
  • 这样子哈,我们基本上就会了,然后我们直接来实战试试。

hdu 2648 “Shopping”

题目链接:点我了解题目(这是一个链接)

题目描述:

每个女孩都喜欢购物,蒲公英也喜欢。现在,由于春节临近,她发现这家商店每天都在涨价。她喜欢一家叫做“记忆”的商店。现在她想知道每天更换后这家商店的价格等级。

输入描述:

一行包含一个数字n(n <= 10000),代表商店的数量。
然后n行,每行包含一个字符串(长度小于31,并且仅包含小写字母和大写字母。)代表商店的名称。
然后一行包含一个数字m(1 <= m <= 50),代表天。
然后m个零件,每个零件包含n条线,每条零件包含数字s和字符串p,代表这一天,商店p的价格增加了s。

输出描述:

包含m行,在第i行后第i行打印多个商店“内存”的等级。我们将等级定义为:如果有t家商店的价格高于“内存”,则其等级为t + 1。

输入样例:

3
memory
kfc
wind
2
49 memory
49 kfc
48 wind
80 kfc
85 wind
83 memory

输出样例:

1
2

  • 先将每个物品进map,设置初始价格为0,后面入值的时候直接 map[物品名称]+=物品增长价值 ,然后利用迭代器进行遍历一次,算出高于memory商品的店数有多少即可。
  • 咳咳,好了,开打。
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	map<string , int > a;   //建立商品名称到商品价格的映射 
	cin >> n;  	//n个商品
	while(~scanf("%d",&n)){			//多组输出值
		a.clear();
		for(int i=0;i<n;i++){
			string str;	
			cin >> str;
			a[str]=0;			//商品初始价格都是0 
		}
		int m;				//m表示天数,v表示当日某商品的增长价格 
		cin >>  m;
		while(m--){
			int ans=0;
			for(int i=0;i<n;i++){
				string str;
				int v;
				cin >> v >> str;
				a[str]+=v;
			}
			map<string,int>::iterator it;
			for(it=a.begin();it!=a.end();it++){
				if(a["memory"]<it->second)ans++;
			}
			cout << ans+1 << endl;		
		}
	}
	return 0;
}
  • 噗,我真吐了,第二次AC,原因是题目是要求多组输入,所有整个程序要进循环的。
  • emmm真菜。
    在这里插入图片描述
  • 这里说一下哈,提交偷懒的话,尽量用G++提交,为什么呢,因为c++他不支持万能库,就是#include<bits/stdc++.h>这是个万能库。
  • 写个这玩意,啥库都能调用了,当然啦,有优点就有缺点,这样虽然你爽了, 但是电脑很不爽,他相对于你单独把那些库写出来,时间上会慢一点,比赛的时候建议还是自己写需要的库名称,平时的话,还是自己爽重要一点,啊哈哈哈哈哈。
  • 反正就是觉得,map跟字符串很配哦,就是好用。
  • 来来来,我们再来搞一道字符串问题,用map做,超级简单。

hdu 1251 “统计难题”

题目连接:点我了解题目(这是一个链接)
题目描述:Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).

输入样例:

banana
band
bee
absolute
acm

ba
b
band
abc

输出样例:

2
3
1
0

  • 我们先分析一波,首先,一个字符串有多少个前缀呢,比如:abcd 的前缀有 a,ab,abc,abcd; 所有我们只需要把这四个投入到map里面后,自加一次就可以了,现在就是如何进行分开投入。
  • 这样,倒过来看, abcd,abc,ab,a; 这样子,我们知道,一个字符串是以它的反斜杠零为结束标志的,我们只需要从后面开始,依次变成反斜杠零就可以了。
  • 好了,知道这个我们就可以直接开打了。
#include<bits/stdc++.h>
using namespace std;
int main(){
	char s[100];
	map<string ,int >mp;
	while(gets(s)){
		int len = strlen(s);
		if(len==0)break;  //表示投入了一个回车换行,直接跳出。
		for(int i=len;i>0;i--){
			s[i]=0;			//注意,在字符串里面,0和'\0'是一样的。 
			mp[s]++;
		} 
	}
	while(gets(s)){
		if(strlen(s)==0)break;
		cout <<  mp[s] << endl;
	}
	return 0;
}
  • 注意哦,这里不能用string 引用字符串类型,因为string并不是以\0为结束标志的字符串。
  • 虽然显示是一样的,但是内部长度还是不一样的,string中0也会当做字符中一的一个字符存入。

在这里插入图片描述

  • 咳咳,可能是因为strlen这个函数,他是以‘\0’为结束标志的,但是length,就是直接求出他的长度的。嗯嗯,就是这样。
  • 行,今天的map就到这里了。
------------------------------2020/12/23------------------------------
  • 今天很兴奋,遇到了字符串问题,前面有说过,字符串和map容器很配哦!

ICPC Chennai 2017 B - Minimize the string

题目链接:点我了解题目(这是一个链接)
题目大意:给您n个字符串s 1,s 2,…,s n。每个字符串仅包含字母“ a”和“ b”,每个字符串的长度最多为2。换句话说,唯一允许的字符串是“ a”,“ b”,“ aa”,“ ab”,“ ba”和“ bb”。

考虑一个置换p = { p 1,p 2,…,p Ñ }整数的{1,2,…,Ñ }。使用此置换,您可以获得新的字符串S = s p 1 + s p 2 + … + s p n,其中运算符+表示字符串的串联。

您可以通过多次执行以下操作来缩短字符串S:选择两个连续相等的字符,然后从字符串中删除这些字符之一。例如,字符串“ aabb”可以在一个操作中缩短为“ abb”或“ aab”,然后可选地,仍可以将其缩短为“ ab”。

您可以选择任何排列p。取用此置换获得的字符串S,并使用任何操作序列,使字符串长度最小。找到可获得的字符串的最小可能长度。

输入样例:

2
2
ba ab
4
a b a b

输出样例:

3
2

  • 题目还是很简单的,就是相等的字符可以互相抵消。
  • 题目还是横简单了,俺又犯傻了,导致错了三次,原因是循环里面用来两个一样变量,害,难受呀!
#include<bits/stdc++.h>
using namespace std;
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		string s;
		map<string , int >mp;
		for(int i=0;i<n;i++){
			cin >> s;
			string str="";
			int f1=1,f2=1;
			for(int j=0;j<s.length();j++){
				if(s[j]=='a'&&f1){str+="a";f1=0;}
				if(s[j]=='b'&&f2){str+="b";f2=0;}
			}
			mp[str]++;
		}
		if(mp["ab"]==0&&mp["ba"]==0)
			if(mp["a"]&&mp["b"])cout << 2 << endl;
			else cout << 1 << endl;
		else{
			if(mp["ab"]==0||mp["ba"]==0){
				if(mp["ab"])cout << mp["ab"]*2 << endl;
				else cout << mp["ba"]*2 << endl;
			}
			else{
				if(mp["ab"]==mp["ba"])cout << 2*mp["ab"]+1 << endl;
				else cout << max(mp["ab"],mp["ba"])*2 << endl;
			}			
		}
		mp.clear();
	}
	return 0;
} 
  • 咳咳,溜了溜了。晚上练习ICPC遇到这玩意,害,气死我了。
------------------------------2020/12/24------------------------------

改革尚未成功,同志仍需努力!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

木木不会

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值