你还在担心不会用auto写for循环吗?
你还在担心map不会用吗?
你还在为STL的各种库不会用而苦恼吗?
相信我,看了这篇文
。
。
。
你依然不会!
题目传送门—>CF977B Two-gram
题目描述:
给你一个字符串,找出现次数最多的长度为2的子串。
输入样例:
7
ABACABA
输出样例:
AB
这道题可以作为C++ STL库的优质练手题
1.auto的循环遍历
for(auto x : range)
创建拷贝,无法修改range中的元素
for(auto& x : range)
可以修改range中的元素,但一般用这种for(auto&& x : range)
for(const auto & x : range)
只读range中的元素
2.string中截取字符串
ss.substr(i,k):
这个的意思就是从i开始截取以k为单位长度的一个字符串,k指代的是长度。
ss.c_str():
这个就是将string字符串转化成为C的字符串数组,而c_str();则是生成一个const char*类型的指针,指向字符串的首地址
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int main(){
char s[10];
string a="hello world!";
strcpy(s,a.c_str());
cout<<s;
}
不妨可以试试.
#include<iostream>
#include<string>
#include<map>
#include<vector>
using namespace std;
int main(){
string ss;
string ans;
map<string,int>f;
int u;
cin>>u;
cin>>ss;
//u=-1;
u=0;
for(int i=0;i<ss.size()-1;i++){
f[ss.substr(i,2)]++;
//注意这里的substr(i,k)是string中的库函数
//这个的意思就是从i开始截取以k为单位长度的
//一个字符串
}
//遍历数组
ans=ss.substr(0,2);
for(auto &&i:f){
if(i.second>u){
u=i.second;
//cout<<u<<endl;
ans=i.first.c_str();
}
}
cout<<ans;
return 0;
}
如果map这么定义:map < string , map < string , int > >
那么应该:
for(auto&&p:m)
for(auto&&p2:p.second)
下面一道题是关于set的用法
现在有N个数,你的任务是将这N个数尽可能切割成多段。每一段必须包括两个相同的数。
数据输入量比较大,建议使用scanf和printf。
Input 单组测试数据。数据第一行为N(1 ≤ N ≤ 3·105) 。
数据的第二行包括N个数ai(1 ≤ ai ≤ 109) 。
Output 输出的第一行为尽可能切割的最大段数K。
接下来K行,每行为两个整数lj, rj (1 ≤ lj ≤ rj ≤ n) ,表示切割的区间范围
如果存在多个合法的切割方法,输出任意一个即可。
如果不能切割成合法的情况,输出"-1".
这道题涉及一小部分贪心
首先讲一下set:
#include <set>//头文件
set <int> st//定义set,我喜欢用st命名
set.insert(a)//插入数据
set.count(a)//查找数据是否出现
set.clear()//清空
快读模板
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
这道题的思路就是用set找到相同的数字了以后就把这个区间切开,但是本道题代码实现相对来说很巧妙,下面请看。
#include<iostream>
#include<set>
using namespace std;
set<int>p;
int l[1010102],r[1010212];
int a[1021021];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}//快读,常数优化大佬中的大佬,不会的赶紧学一下吧!
int main(){
int n;
n=read();
l[1]=1;
int u=0;
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++){
if(p.count(a[i])==1){
++u;
r[u]=i;
l[u+1]=i+1;
p.clear();//已经裁剪,全部清空
//这道题的大致意思就是我们找到重复的了
//那么就说我们我们找到了一组可裁剪区间
//l[1]=1说明我们裁剪的话肯定先要裁剪第一个
//然后让下一位裁剪的位置指向下一个第一位
//确定完裁剪区间以后,我们就认为这个区间和
//我们题干中的数组没关系了,就清空set集合
}else p.insert(a[i]);
/*if(p.count(a[i])==1){
r[u]=i;
l[++u]=i+1;
p.clear();//已经裁剪,全部清空
}else p.insert(a[i]); **////这个是错的!注释的部分和答案不一样的地方在于
//
}
r[u]=n;//这个是精髓之处
//比方说1 2 2 2 2 1 3 本来r[1]=6,但是为了让最后的数字包括上
//就自动赋值让r[1]=7
if(u==0){
printf("-1\n");
return 0;
}
else {
/*if(r[u-1]==n){
cout<<u-1<<endl;
for(int i=1;i<u;i++){
cout<<l[i]<<' '<<r[i]<<' ';
}
}else */{
cout<<u<<endl;
for(int i=1;i<=u;i++){
cout<<l[i]<<' '<<r[i]<<endl;
}
}
}
return 0;
}
priority_queue C++ STL库中的优先队列
头文件:#include 和普通的queue不一样的地方在于:可以自定义数据的优先级(权重),让权重高的排在队列的前方,优先出队。本质上是堆的一个实现。
定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。
当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。
//升序队列,小顶堆(从小到大输出)
priority_queue <int,vector,greater > q;
//降序队列,大顶堆 (从大到小输出)
priority_queue <int,vector,less >q;
//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)