22.1.14

一.oj补题

2.Train and Peter

题意就是给你两个字符串,判断第二个字符串能否正序存在于第一个字符串,或者反序~或者都存在,或者不存在;先看题解:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    string s,s1,s2;
    cin>>s>>s1>>s2;
    bool flag1=false,flag2=false;
    if(s.find(s1)!=s.npos && s.find(s2,s.find(s1)+s1.size())!=s.npos)
        flag1=true;
    reverse(s.begin (),s.end());
    if(s.find(s1)!=s.npos && s.find(s2,s.find(s1)+s1.size())!=s.npos)
        flag2=true;
    if(flag1 && flag2)
        cout<<"both"<<endl;
    else if(flag1)
        cout<<"forward"<<endl;
    else if(flag2)
        cout<<"backward"<<endl;
    else
        cout<<"fantasy"<<endl;
    return 0;
}

通过查找csdn的各种题解,这是我发现的最简洁明了的一个。其强大之处个人认为熟练运用了STL,在刷题过程中,碰到了STL一定要掌握好才是;

①find函数()针对string类用的(12条消息) C++中find函数用法_小白_努力-CSDN博客_c++find函数用法https://blog.csdn.net/laobai1015/article/details/62426137?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164211979016781683984660%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164211979016781683984660&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-62426137.first_rank_v2_pc_rank_v29&utm_term=find%E5%87%BD%E6%95%B0&spm=1018.2226.3001.4187

s1.find(s2)返回的是s2在s1中第一次出现的位置!所以搭配find(s2,location)的用法;

如果没有查找到,则返回的是npos;

 当然好像还有#include<algorithm>中的find()函数(12条消息) find()函数及其他常用函数总结_纸短情长的博客-CSDN博客_函数findhttps://blog.csdn.net/qq_41376345/article/details/104283832?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164211979016781683984660%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164211979016781683984660&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-104283832.first_rank_v2_pc_rank_v29&utm_term=find%E5%87%BD%E6%95%B0&spm=1018.2226.3001.4187

 ②reverse()的用法,三个:数组,字符串,向量;(12条消息) C++中的reverse()函数_YMWM_的博客-CSDN博客_reversehttps://blog.csdn.net/YMWM_/article/details/115468297?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164212204616780261991594%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164212204616780261991594&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-4-115468297.first_rank_v2_pc_rank_v29&utm_term=reverse&spm=1018.2226.3001.4187

③ 这是我写的,但是为什么用scanf会出错呢。感觉输入上有了问题,改成cin就没错了;但是cin用时会长些,可恶啊!!!;好好研究下scanf把!;

#include<bits/stdc++.h>

using namespace std;

string s,s1,s2;
int main()
{
	
	scanf("%s",&s);
	scanf("%s",&s1);
	scanf("%s",&s2);
	bool flag1=0,flag2=0;
	int l1=s1.size();
	if(s.find(s1)!=s.npos&&s.find(s2,s.find(s1)+l1)!=s.npos)flag1=1;
	reverse(s.begin(),s.end());
	if(s.find(s1)!=s.npos&&s.find(s2,s.find(s1)+l1)!=s.npos)flag2=1;
	if(flag1&&flag2)cout<<"both\n";
	else if(flag1)cout<<"forward\n";
	else if(flag2)cout<<"backward\n";
	else cout<<"fantasy";
	return 0;
}

 3. Keyboard

题意就是,其实我觉得这个就是个交互题,只不过前后思路得清晰;这里借下同学写的思路:

从头到尾遍历目标函数,一一判断能不能打出当前字符,

1.如果遇到的是小写字母,如果键盘里面有就可以单手打出

2.如果遇到的是大写字母,如果键盘里面没有‘S’键或者没有对应的小写字母就输出-1,如果两者都具备可以比较所有的‘S’键和所有的该对应字母的距离,取最小值即可,如果它大于x就需要用到双手,计数++

AC代码

#include<iostream>
#include<math.h>
#include<map>
using namespace std;
int n,m,l;
char a[35][35];//键盘字符
map<char,int>f;//标记该字母是不是在键盘出现过,1表示有,0表示没有
int posx[1010],posy[1010];//所有‘S’键的坐标位置
int k;//有多少个‘S’键
int res;//用到双手的次数
int main()
{
    cin>>n>>m>>l;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            if(a[i][j]>='a'&&a[i][j]<='z')f[a[i][j]]=1;//标记出现过的小写字母
            else if(a[i][j]=='S'){
                k++;
                posx[k]=i,posy[k]=j;//存储‘S’键的位置
            }
        }
    }
    int len;
    char str[500010];
    cin>>len>>str+1;//输入目标字符串及长度
    for(int i=1;i<=len;i++){
        if(str[i]>='a'&&str[i]<='z'){
            if(f[str[i]]==0){
                cout<<-1;//如果是小写字母只需要判断是不是在键盘中出现过
                return 0;
            }
        }
        else if(str[i]>='A'&&str[i]<='Z'){
            if(f[str[i]+32]==0||k==0){
                cout<<-1;//如果是大写字母,判断有没有‘S’键或者对应的小写字母
                return 0;
            }
            else{
                double minn=0x3f3f3f;//寻找最小距离
                for(int j=1;j<=k;j++){
                    for(int w=1;w<=n;w++){
                        for(int q=1;q<=m;q++){
                            if(a[w][q]==str[i]+32)minn=min(minn,sqrt((posx[j]-w)*(posx[j]-w)+(posy[j]-q)*(posy[j]-q)));
                        }
                    }
                     
                }
                if(minn>l)res++;//如果最小距离比它大,计数++
            }
        }
    }
    cout<<res;//输出结果
    return 0;
}

4.Queue

题意,研究了两个小时,去cf看才发现这是dive1的题,不得不说我还是太菜了。。;加紧学习吧!!此题先放一放;

二.AcWing算法学习

1.高精度减法

#include<bits/stdc++.h>

using namespace std;


//判断是否有A>=B;
bool cmp(vector<int>&A,vector<int>&B)
{
	if(A.size()!=B.size())return A.size()>B.size(); //长度不等,直接判断;
	for(int i=A.size()-1;i>=0;i--)//长度相等,从高位开始,逐个比较大小;
	{
		if(A[i]!=B[i])return A[i]>B[i];
	}
	return true;
}
vector<int> sub(vector<int>&A,vector<int>&B)
{
	vector<int>C;
	for(int i=0,t=0;i<A.size();i++)
	{
		t=A[i]-t;
		if(i<B.size())t-=B[i];
		C.push_back((t+10)%10);//t>=0,10和10消了;t<0,就是t+10;
		if(t<0)t=1;
		else t=0;
	}
	while(C.size()>1&&C.back()==0)C.pop_back();//删除前导0;123-120;003~3;
	return C;
}
int main()
{
  string a,b;
  vector<int>A,B;
  cin>>a>>b;
  for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');//存进来的是符号,减去‘0’
  for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');//可以成为真实的算数值;ASCII码问题;
  
  vector<int>C;
  if(cmp(A,B))C=sub(A,B);
  else C=sub(B,A),cout<<"-";
  for(int i=C.size()-1;i>=0;i--)cout<<C[i];
  cout<<endl;
  
    return 0;
}

 ①这里补充一下vector的内置函数的一些操作

#include<vector>
vector<int> a,b;
//b为向量,将b的0-2个元素赋值给向量a
a.assign(b.begin(),b.begin()+3);
//a含有4个值为2的元素
a.assign(4,2);
//返回a的最后一个元素
a.back();
//返回a的第一个元素
a.front();
//返回a的第i元素,当且仅当a存在
a[i];
//清空a中的元素
a.clear();
//判断a是否为空,空则返回true,非空则返回false
a.empty();
//删除a向量的最后一个元素
a.pop_back();
//删除a中第一个(从第0个算起)到第二个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)结束
a.erase(a.begin()+1,a.begin()+3);
//在a的最后一个向量后插入一个元素,其值为5
a.push_back(5);
//在a的第一个元素(从第0个算起)位置插入数值5,
a.insert(a.begin()+1,5);
//在a的第一个元素(从第0个算起)位置插入3个数,其值都为5
a.insert(a.begin()+1,3,5);
//b为数组,在a的第一个元素(从第0个元素算起)的位置插入b的第三个元素到第5个元素(不包括b+6)
a.insert(a.begin()+1,b+3,b+6);
//返回a中元素的个数
a.size();
//返回a在内存中总共可以容纳的元素个数
a.capacity();
//将a的现有元素个数调整至10个,多则删,少则补,其值随机
a.resize(10);
//将a的现有元素个数调整至10个,多则删,少则补,其值为2
a.resize(10,2);
//将a的容量扩充至100,
a.reserve(100);
//b为向量,将a中的元素和b中的元素整体交换
a.swap(b);
//b为向量,向量的比较操作还有 != >= > <= <
a==b;

 ②还有对retun 一个不等式的理解,本质上讲呢,a>b可以看作一个判断式,当a>b时,a>b的值为1(true),a<=b时,a>b的值为0(false),所以return a>b;就是在判断a是否大于b;

2.高精度乘法(大整数*小整数)

具体实现呢,是把小整数当作一个整体去和大整数的每一位相乘,最终得出结果;

#include<bits/stdc++.h>
using namespace std;
vector<int> mul(vector<int> &A, int b)
{
    vector<int> C;

    int t = 0;
    for (int i = 0; i < A.size() || t; i ++ )//如果没有乘完A的长度,或者仍处在进位;
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();//为0的情况;

    return C;
}


int main()
{
    string a;
    int b;

    cin >> a >> b;

    vector<int> A;
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');

    auto C = mul(A, b);

    for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);

    return 0;
}

3.高精度除法(大整数/小整数)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//int r=0;
vector<int> div(vector<int> &A,int B,int &r){//r传入r的地址,便于直接对余数r进行修改
    vector<int> C;
    for(int i=0;i<A.size();i++){//对A从最高位开始处理
        r=r*10+A[i];//将上次的余数*10在加上当前位的数字,便是该位需要除的被除数
        C.push_back(r/B);//所得即为商在这一位的数字
        r=r%B;
    }
    //由于在除法运算中,高位到低位运算,因此C的前导零都在vector的前面而不是尾部,vector只有删除最后一个数字pop_back是常数复杂度,而对于删除第一位没有相应的库函数可以使用,而且删除第一位,其余位也要前移,
    //因此我们将C翻转,这样0就位于数组尾部,可以使用pop函数删除前导0
    reverse(C.begin(),C.end());
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}
int main(){
    string a;
    int B,r=0; //代表余数
    cin>>a>>B;
    vector<int> A;
    for(int i=0;i<a.size();i++) A.push_back(a[i]-'0');//注意这次的A是由高为传输至低位,由于在除法的手算过程中,发现从高位进行处理
    //for(int i=0;i<A.size();i++) cout<<A[i];
    //cout<<B;
    auto C = div(A,B,r);
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];//将C从最高位传给最低位
    cout<<endl<<r;//输出余数
    cout<<endl;
    return 0;
}

作者:过眼云烟1
链接:https://www.acwing.com/solution/content/2108/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三.训练赛

2.思维题

题意:给你一串包含1~k(整数)的共n个数字的数串,找出来该数串不包含的最短的子串的长度;

例:给你112233,不包含的最短的是(2,1)为2;

思路:每出现一轮1~k,那么它包含的字串长度+1,同时最短的长度也+1;

代码实现

#include<bits/stdc++.h>

using namespace std;
const int N=1e5+9;
const int M=1e4;
int a[N];
int hs[M];
int n,k;
int main()
{		

	cin>>n>>k;
	int num=k,ans=0;
	memset(hs,0,sizeof hs);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		if(hs[a[i]]==0)
		{
			hs[a[i]]=1;
			num--;
		}
		if(num==0)
		{
			memset(hs,0,sizeof hs);
			ans++;
			num=k;
		}
	}
	cout<<ans+1;	
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Dull丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值