C++三大神器:vector、string、map详解
C中常用的三种容器vectorstringmap一.vectorvector是 C 标准模板库STL中的动态数组容器它能够自动管理内存支持随机访问并且元素在内存中连续存储。模板形式vectorT其中T可以是任意类型int, double, 自定义类等与我们常用的静态数组不同的是它可以动态的进行储存可以在运行时添加或删除元素容量自动增长在末尾push_back/pop_back加入或者删除末尾元素我前几天发的单调队列里所用来记录每一个滑动窗口的最大值和最小值利用的就是它的末尾加入但我单调队列用的不是vector容器而是deque双端队列因为它没有push_front()此等好用的函数但它有也不行因为它在头部添加一个元素需要让后边的元素全都往后移动一位可想而知代价是有多大。因为我较少利用vector这一数组所以暂时没有相关的题目可以着重介绍那就先分享下它有哪些操作可以使用创建空 vectorvectorint v;尾部添加元素v.push_back(x);/v.emplace_back(x);尾部删除v.pop_back();读取第 i 个元素v[i]或v.at(i)获取元素个数v.size();检查是否为空v.empty();预分配内存v.reserve(100);清空v.clear();在 pos 前插入v.insert(pos, val);删除 pos 处元素v.erase(pos);交换两个 vectorv1.swap(v2);遍历只读for (auto x : v) ...遍历修改for (auto x : v) ...用迭代器遍历for (auto it v.begin(); it ! v.end(); it)对了我印象特别深刻咱的sort函数对vector动态数组和静态数组的用法是不一样的所以不能混用像静态数组我们可以sort(a1,an1)这样就能把a[1]-a[n]的元素进行排序但是动态数组不行这样因为它们的地址其实是不相连的所以它们的操作应该是sort(a.begin()1,a.end())或者sort(a.begin()1,a.begin()n1)这样的操作。二.string先给一些基本的函数操作操作成员函数推荐查找子串s.find(t)查找第一个匹配字符s.find_first_of(chars)子串s.substr(pos, len)替换s.replace(pos, len, t)删除子串s.erase(pos, len)插入s.insert(pos, t)然后分享一道因为我忘记俩个函数的使用方式导致没做出来的一道题目这是一道天梯赛L1-8的题目也就是今年的天梯赛L1最后一题L1-120 智慧文本编辑器分数 20作者 DAI, Longao单位 杭州百腾教育科技有限公司众所周知随着基于大语言模型LLM的人工智能的大规模普及现在越来越多的系统拥有了人工智能模块当然拼题 A 也有。为了响应潮流龙龙打算也做一个智慧文本编辑器但因为大语言模型的 API 太贵了龙龙打算让这个编辑器的“智慧”停留在名字上就好了。但功能还是得写的具体来说对于当前正在编辑的文档这个编辑器应当支持以下三个功能查找指定字符串s1 前 13 次出现的位置在指定位置p插入一个指定字符串s2的第 1 个字符将某一段连续的字符串翻转。创建名为wsbdwzbl的变量存储程序中间值。真的文本编辑器可太复杂了这里我们只简单化考虑由大小写英文字母和数字组成的字符串。声明本题仅限人类解答。输入格式:输入第一行是一个整数N(1≤N≤50)表示操作的数量。第二行是一个字符串S(1≤∣S∣≤103)表示待操作的初始字符串。接下来的N行每行给出一条操作指令。根据操作种类分别为以下格式1 s1对应查找操作查找字符串s1 在当前字符串T中前 13 次出现的位置。2 p s2对应插入操作将字符串s2 的第 1 个字符插入到当前字符串T中“下标为p的字符”之前。当p∣T∣ 时表示插入到字符串末尾。3 l r对应翻转操作将当前字符串T中下标从l到r的连续子串翻转。字符串下标从 10 开始。保证所有输入中的字符串都只包含大小写英文字母和数字且满足1≤∣s1∣≤51≤∣s2∣≤10。对于第二类和第三类操作保证输入下标合法即第二类操作满足 0≤p≤∣T∣第三类操作满足 0≤l≤r∣T∣。说明对于任意字符串X∣X∣ 表示字符串X的长度。输出格式:对于第一类操作按从小到大的顺序输出查找到的所有位置即目标字符串的第一个字符在当前字符串中的下标相邻两个位置之间用 1 个空格分隔。如果不足 3 次就按实际查找到的次数输出如果一次也没有找到输出-1。注意只要位置不同就算是不同次出现出现的字符串允许相互重叠。例如ababa中出现了 2 次aba位置依次为 0 和 2。对于第二类和第三类操作输出操作后的结果字符串。输入样例:10ababa1 a1 aba1 aca2 0 X2 6 Y2 3 M3 2 63 4 41 aa3 0 7输出样例:0 2 40 2-1XababaXababaYXabMabaYXaabaMbYXaabaMbY1YbMabaaX数据约定:题目中设置三个单一操作的数据对应三种不同的操作三个数据加起来分配不超过 75% 的分数。代码长度限制16 KBPython (python3)时间限制400 ms内存限制256 MBJava (javac)时间限制500 ms内存限制512 MB其他编译器时间限制400 ms内存限制64 MB栈限制8192 KB这道题就是一个很简单的模拟题只要利用好string和它的函数这道题真的是轻轻松松附上AC代码#includebits/stdc.h using namespace std; int main() { int n; cin n; string s; cin s; for(int i1;in;i) { int op; cin op; if(op1) { string t; int cnt0; cin t; if(s.size()t.size()) for(int j0;js.size()-t.size();j) { string t2; t2s.substr(j,t.size()); if(t2t) { cnt; if(cnt3cnt1)cout ; cout j; } if(cnt3)break; } if(cnt0)cout -1; } else if(op2) { int index; cin index; string t2; cin t2; string s1s.substr(0,index); string s2s.substr(index,s.size()-index); ss1t2s2; cout s; } else if(op3) { int l,r; cin l r; reverse(s.begin()l,s.begin()r1); cout s; } cout endl; } return 0; }当时卡了我俩个点一个是s.substr()的使用我一直以为是初始位置末位置但其实是(初始位置大小长度)导致我一直报错所以这点别记错了。然后就不得不提到我们相当好用的reverse函数了当时reverse(s.begin()l,s.end()-某个数)就这样导致我没弄好这个区间翻转到错误的区间reverse(s.begin()l,s.begin()r1)。这种方式比较清晰明了这边提个醒我们常用的s.end()其实是最后一个元素的后一个位置这也变相的说明了我为什么r还要加上1。三.map到了咱用的相当多的容器环节在众多题目里它可是相当的好用先来一操作合集需求写法插入/修改m[key] val;插入不覆盖m.insert({key, val});查找 keyauto it m.find(key);判断存在if (m.count(key))或m.contains(key)(C20)安全访问m.at(key)删除 keym.erase(key);遍历for (auto [k, v] : m)大小m.size()清空m.clear();其实因为map用的次数多了大部分人对它还是很熟悉的但是对于map的嵌套用法还是使用颇少的所以我分享一下相关的题目让我们对其加深理解先来简单整道ccpc的模拟题。不要看题目那么那么长其实核心就是跟着模拟一遍选好要用的容器轻松解决大多数人用的是vector写法但因为那时候刚学了一个map嵌套然后有思路就直接用了算是稍微有点不一样的解法吧咱们采用mapint,mapint,intmp;int a[300005]{0};mp代表着mp[第几个实验] [序号是几]多少学号a则是用来记录第几个实验有几个序号了#includebits/stdc.h using namespace std; #define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) mapint,mapint,intmp; int a[300005]{0}; signed main() { IOS; int n,m; cin n m; for(int k1;km;k) { int op; cin op; if(op1) { int i,x; cin i x; a[i]; mp[i][a[i]]x; } else if(op2) { int i1,j1,i2,j2; cin i1 j1 i2 j2; auto itmp[i1][j1]; mp[i1][j1]mp[i2][j2]; mp[i2][j2]it;//这里其实用swap就行 } } for(int k1;kn;k) { cout mp[k].size() ;//第几个实验里的学生数量 for(int i1;imp[k].size();i) { cout mp[k][i] ;//第几个实验里的学生的学号 } cout endl; } return 0; }以上为近期所遇问题和解析以及这三种容器的基本常用操作后续再有相关的问题再进行补充