今天来刷2023年睿抗本科省赛比赛的第二题:出院,题目如下:
输入样例
5 6
Diet A
LowSugarTea B
Milk C
Coke D
Water A
DietCoke
Pepsi
Milk
CokeWater
GoodMilk
dietCoke
输出样例
AD
D
C
DA
D
D
首先先来看看我写的代码:
#include <bits/stdc++.h>
using namespace std;
//多种拆解方法 应该怎么办???
//为什么答案错误???
//我明明一模一样
string str[100];
char ch[100];
int main()
{
int N,M,i;
cin>>N>>M;
int k=0,m=0;
string name="";
string s;
for(i=0;i<N;i++){
cin>>str[i];
cin>>ch[i];
}
while(M--){
cin>>s;
k=0;
m=0;
for(i=0;i<N;i++){
if(s.find(str[i])>=0){
name+=ch[i];
k++;
}
if(s==str[i]){
m=1;
}
}
if(k==0||(k==1&&m!=1)){
name="D";
}
cout<<name<<endl;
name.clear();
}
}
错误分析:
1.为什么我的输出明明是一样的,但是交上去还是说我答案错误?
2.思维上还有哪些欠缺?
3.和其他人的差距在哪
4.提交上去后编译器里边说我的这一句s.find(str[i])>=0这句话有问题
分析过程
1.我的思路是在需要定级的饮料里边寻找已知到的饮料的名字,再通过黏合字符串把等级输出,但是由于题目是需要把它分解为两个串或者直接是已知的串,所以我这种找字符串的方式对于只有一个串的情况或者不能完全分为两个串的情况很难办,还要再改进一下
2.突然想到是不是可以先判断是不是和已知情况有相符合的,然后再来找子串?
3.不过看别人的题解可能分解子串会更简便一点,我先把第二点的思路改进一下
4.有编译警告的可以改成s.find(str[i])!=string::npos 用string里边的npos
5.又写了一遍,一分,气死我了
#include <bits/stdc++.h>
using namespace std;
//多种拆解方法 应该怎么办???
//为什么答案错误???
//我明明一模一样
string str[100];
char ch[100];
int main()
{
int N,M,i;
cin>>N>>M;
int k=0,flag=0;
string name="";
string s;
for(i=0;i<N;i++){
cin>>str[i];
cin>>ch[i];
}
while(M--){
cin>>s;
k=0;
flag=0;
for(i=0;i<N;i++){
if(s==str[i]){
cout<<ch[i]<<endl;
flag=1;
break;
}
} //首先判断是不是已知的串
if(flag==1){
continue;
}else{
for(i=0;i<N;i++){
if(s.find(str[i])!=string::npos){
name+=ch[i];
k++;
}
} //用来判断是不是可以分成两个串
if(k==2){
cout<<name<<endl;
}else{
cout<<"D"<<endl;
}
}
name.clear();
}
}
好吧,我屈服了,来看看别人的代码,总结一下别人的代码思路
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
map<string, string> mp; //1.使用了map 理由:给定拥有等级的饮料的名字不会重复
for(int i = 1;i <= n; ++ i) {
string s1, s2;
cin >> s1 >> s2;
mp[s1] = s2; //字符串为键,等级为值
}
while(m --) {
string s;
cin >> s;
if(mp.count(s)) { //2.map中的count函数 ,用来判断键是否存在,只会返回0和1两种结果
cout << mp[s] << '\n';
continue;
}
int cnt = 0;
string ans = "";
for(int i = 1; i < (int)s.size(); ++ i) {
string s1 = s.substr(0, i), s2 = s.substr(i); //3.用string里边的substr函数把字符串分解成两个子串
if(mp.count(s1) && mp.count(s2)) {
++ cnt; //4.cnt是用来判断是否存在多种分割方式的
ans = mp[s1] + mp[s2];
}
}
if(ans.empty() || cnt > 1) cout << "D\n";
else cout << ans << '\n'; //5.对应了题目里边的第三句话 ,如果无法拆解或者有多种拆解方式
}
return 0;
}
经验总结:
1.我通过改进以后的代码思路在顺序上有点类似,但是还是实现的不够细致,对于每一道题目的题干的理解还不够深入,有点太依照自己的想法去实现了,对题目研读不够细致,有点发散思维
待学习的知识的总结
1.map容器的应用,定义
map容器是含有键值对的容器,其中第一个代表键,且是唯一的,第二个代表值,其中这个题目说了两个东西是联系在一起的,而且有一个东西是唯一的,所以用map来存放数据再适合不过了
2.map容器的count函数的应用
返回值方面:只会返回0或者1,用来判断键是否存在
3.string里边的substr函数
左闭右开
学习思路的总结
1.分成两个子串,就可以用substr截两次,把它的每一种可能截出来的情况都比较出来,就能知道到底是否有多种分法
重写一遍这个题目放在明天,敬请看明天的每天一刷。