当前位置: 代码迷 >> 综合 >> [CSP]201712-3 Crontab (恶心的)string处理 大模拟
  详细解决方案

[CSP]201712-3 Crontab (恶心的)string处理 大模拟

热度:44   发布时间:2023-12-16 22:17:06.0

题目链接:http://118.190.20.162/view.page?gpid=T66

然后贴上一份别人比我写得好看的代码:https://blog.csdn.net/banana_cjb/article/details/79174688

不得不说,不提前规划好怎么写,或者不用C++的string,或者写代码的时候不够心细,处理起来是很恶心的。所以考试的时候一定要先写简单的部分,否则这题性价比挺低的,尤其是错了点细节可能会让你写了上百行的代码得20分。

 

本人遇到的问题:

1.数组下标写错。代码能力所致。

2.erase写错,因为是多重遍历,跳出循环需要处理一下字符串。所以提前规划好要怎么写是很重要的,不要中途改来改去。

3.日期数错。这个就尴尬了,用了一个数组记某个月过去这一年多少天,也就是31.28.31.30...的前缀数组。但是我算错了一个数,硬生生少了40分。

4.看错题忽略掉关键细节。首先Jun这种表示法,大小写都有可能。最后的15分看了别人的代码才发现错哪了。然后数据范围是左闭右开。

5.整数和字符串转化问题。不同于java,这里的string拼接整数,不能用+加号,或者直接构造,否则会出现奇怪的结果。然后整数转字符串可以注意一下补位的问题。

6.合法数据的额外判断。4月31号, 非闰年的2月29号等之类的数据要额外排除掉。

 

然后string的一些用法:

1.size()和length()。取得字符串长度。size等同于其他STL,length在string中刚好是同义词,就是说用哪个都可以。

2.at()和[]。取得某个位置的元素可以用at(i)后者直接下标访问。

3.+和append。用来拼接。append可以添加另一个字符的子串(string str, int pos, int len),或者多个相同字符(int time, char ch)

4.erase。用来删除从pos开始的len长度的字符(int pos, int len)。或删除一个或两个迭代器之间的字符。

5.find。用来查找某个字符串中某字符/串第一次出现的位置,没有返回npos。(str/char,pos=0).

6.substr。返回某个字符串从pos开始,长度为len的子串。

7.replace。把某个字符串,从pos开始,长度为len的串,替换成新串。(pos, len, string newstr)

 

然后处理逻辑:每个指令存5个string类型的vector,分别记录其合法分、小时、天、月、星期的两位字符串。通过遍历找到所有合法组,用星期和范围判断是否是一个指令,把拼接成的字符串存起来,最后通过排序得到按时间排序的指令集。

数据处理:

1.将Week和Month的英文串替换成数字。用两个数组遍历查找一遍即可。

2.将可能出现的数字替换成两位的字符串。可能会有补位问题。

3.处理*。如果是*将范围内所有数丢进vector。

4.否则按步骤循环处理每个,

5.在处理一组,隔开的解时,判断是否有-,有则转换整数将范围内所有数丢进vector,否则将整体丢进vector。

遍历判断:

1.通过5重循环(年、月、日、时、分)拼接字符串,一边拼接一边判断是否超过范围,超过修改str并continue.

2.遍历之前判重,避免插入重复数据(理论上来说不会)

3.走到最内层时。将特殊不合法日期去掉。并计算一下星期,查找是否在合法week_vector中,如果不在去掉。

 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const string Months[] = {" ", "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
const string Weekdays[] = {"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
const int Dnum[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};string sttime, edtime;//起止时间,左闭右开
typedef struct Ans
{string time, work;}Ans;
vector<Ans>ans;//答案组,多条指令不清空。
bool cmp(const Ans &a, const Ans &b)
{return a.time < b.time;
}class Order
{vector<string> mm, hh, DD, MM, Wek;string work;void init(){mm.clear(), hh.clear(), DD.clear(), MM.clear(), Wek.clear();}//----------- string和int转换--------------int stoi(string str){//cout<<"stoi:"<<str<<endl;int ret = 0;while(str != ""){ret *= 10;ret += str.at(0) - '0';str = str.substr(1, str.size() - 1);}return ret;}string itos(int ipt){string ret = "";while(ipt){char ch = ipt % 10 + '0';ipt /= 10;ret = ch + ret;}while(ret.size() < 2)ret = '0' + ret;return ret;}//------------修改过的replaceAll(C++里没有)--------------string replaceAll(string oldstr, string old_value, string new_value){//cout<<"replaceAll"<<oldstr<<": "<<old_value<<"->"<<new_value<<endl;int pos = 0;for(int i = 0; i < oldstr.length(); i++)if(oldstr[i] <= 'Z' && oldstr[i] >= 'A')oldstr[i] = oldstr[i] - 'A' + 'a';while((pos=oldstr.find(old_value))!=string::npos)   {oldstr = oldstr.replace(pos,old_value.size(),new_value);}return oldstr;}//------------分别处理5个数据。因为逻辑基本相同,理论上来说可以带上vector参数用一个函数实现。void convMin(string str){string strn;string pb;if(str == "*"){for(int i = 0; i < 60; i++){pb = itos(i); mm.push_back(pb);}}else {while(str != ""){int pos;if((pos = str.find(',')) != string::npos){strn = str.substr(0, pos);str = str.substr(pos+1, str.size() - pos);}else {strn = str; str = "";}int posn;if((posn = strn.find('-')) != string::npos){string left = strn.substr(0, posn);int il = stoi(left);string right = strn.substr(posn+1, strn.size()-posn);int ir = stoi(right);for(int i = il; i <= ir; i++){pb = itos(i); mm.push_back(pb);}}else mm.push_back(itos(stoi(strn)));}}/*cout<<"mm:"<<endl;for(int i = 0; i < mm.size(); i++)cout<<mm[i]<<" ";cout<<endl;*/}void convHour(string str){string strn;string pb;if(str == "*")for(int i = 0; i < 24; i++){pb = itos(i); hh.push_back(pb);}else {while(str != ""){int pos, posn;if((pos = str.find(',')) != string::npos){strn = str.substr(0, pos);str = str.substr(pos+1, str.size() - pos);}else {strn = str; str = "";}if((posn = strn.find('-')) != string::npos){string left = strn.substr(0, posn);int il = stoi(left);string right = strn.substr(posn+1, strn.size()-posn);int ir = stoi(right);for(int i = il; i <= ir; i++){pb = itos(i); hh.push_back(pb);}}else hh.push_back(itos(stoi(strn)));}}/*cout<<"hh:"<<endl;for(int i = 0; i < hh.size(); i++)cout<<hh[i]<<" ";cout<<endl;*/}void convDay(string str){string strn;string pb;if(str == "*")for(int i = 1; i < 32; i++){pb = itos(i); DD.push_back(pb);}else {while(str != ""){int pos, posn;if((pos = str.find(',')) != string::npos){strn = str.substr(0, pos);str = str.substr(pos+1, str.size() - pos);}else {strn = str; str = "";}if((posn = strn.find('-')) != string::npos){string left = strn.substr(0, posn);int il = stoi(left);string right = strn.substr(posn+1, strn.size()-posn);int ir = stoi(right);for(int i = il; i <= ir; i++){pb = itos(i); DD.push_back(pb);}}else DD.push_back(itos(stoi(strn)));}}/*cout<<"DD:"<<endl;for(int i = 0; i < DD.size(); i++)cout<<DD[i]<<" ";cout<<endl;*/}void convMon(string str){string strn;string pb;for(int i = 1; i <= 12; i++){pb = itos(i);str = replaceAll(str, Months[i], pb);}if(str == "*")for(int i = 1; i < 13; i++){pb = itos(i);MM.push_back(pb);}else {int pos, posn;while(str != ""){if((pos = str.find(',')) != string::npos){strn = str.substr(0, pos);str = str.substr(pos+1, str.size() - pos);}else {strn = str; str = "";}if((posn = strn.find('-')) != string::npos){string left = strn.substr(0, posn);int il = stoi(left);string right = strn.substr(posn+1, strn.size()-posn);int ir = stoi(right);for(int i = il; i <= ir; i++){pb = itos(i);MM.push_back(pb);}}else MM.push_back(itos(stoi(strn)));}}}void convWek(string str){string strn;string pb;for(int i = 0; i < 7; i++){pb = itos(i);str = replaceAll(str, Weekdays[i], pb);}if(str == "*")for(int i = 0; i < 7; i++){pb = itos(i); Wek.push_back(pb);}else {int pos , posn;while(str != ""){if((pos = str.find(',')) != string::npos){strn = str.substr(0, pos);str = str.substr(pos+1, str.size() - pos);}else {strn = str; str = "";}if((posn = strn.find('-')) != string::npos){string left = strn.substr(0, posn);int il = stoi(left);string right = strn.substr(posn+1, strn.size()-posn);int ir = stoi(right);//cout<<left<<" -- "<<right<<endl;for(int i = il; i <= ir; i++){pb = itos(i); Wek.push_back(pb);}}else Wek.push_back(itos(stoi(strn)));}}return ;}//-------判断闰年和查找星期------------bool luyear(int year){return year%400 == 0 || (year%100 != 0 && year%4 == 0);}int getWeekday(string str){int ans = 4;int year = stoi(str.substr(0, 4));int month = stoi(str.substr(4, 2));int day = stoi(str.substr(6, 2));for(int i = 1970; i < year; i++){if(luyear(i))ans += 2;else ans += 1;}ans %= 7;ans += Dnum[month-1];if(luyear(year) && month > 2)ans++;ans %= 7;ans += day-1;ans %= 7;return ans;}//创建ans组集void getAns(){string str;sort(mm.begin(), mm.end());sort(hh.begin(), hh.end());sort(DD.begin(), DD.end());sort(MM.begin(), MM.end());sort(Wek.begin(), Wek.end());for(int y = stoi(sttime.substr(0, 4)); y <= stoi(edtime.substr(0, 4)); y++){for(int l = 0; l < MM.size(); l++){if(l > 0 && MM[l] == MM[l-1]){str.erase(4, 2);continue;}str = itos(y) + MM[l];if(str < sttime.substr(0, 6) || str > edtime.substr(0, 6)){str.erase(4, 2);continue;}for(int k = 0; k < DD.size(); k++){str = itos(y) + MM[l] + DD[k];if(k > 0 && DD[k] == DD[k-1]){str.erase(6, 2);continue;}if(str < sttime.substr(0, 8) || str > edtime.substr(0, 8)){str.erase(6, 2);continue;}for(int j = 0; j < hh.size(); j++){if(j > 0 && hh[j] == hh[j-1]){str.erase(8, 2);continue;}str = itos(y) + MM[l] + DD[k] +  hh[j];if(str < sttime.substr(0, 10) || str > edtime.substr(0, 10)){str.erase(8, 2);continue;}for(int i = 0; i < mm.size(); i++){if(i > 0 && mm[i] == mm[i-1]){str.erase(10, 2);continue;}//判重if(DD[k] == "31" && (MM[l] == "04" || MM[l] == "06" || MM[l] == "09" || MM[l] == "11" || MM[l] == "02")){str.erase(10, 2);continue;}//去掉非法日期if(MM[l] == "02" && (DD[k] == "30" || (DD[k] == "29" && !luyear(y)))){str.erase(10, 2);continue;}str = itos(y) + MM[l] + DD[k] +  hh[j]+ mm[i] + '\0';if(str < sttime.substr(0, 12) || str >= edtime.substr(0, 12)){str.erase(10, 2);continue;} //判断范围int gwed = getWeekday(str);string sgwed = itos(gwed);bool flag = false;for(int m = 0; m < Wek.size(); m++){//判断合法星期if(Wek[m] == sgwed)flag = true;}if(flag == false){str.erase(10, 2);continue;}Ans now;now.time = str, now.work = work;ans.push_back(now);str.erase(10, 2);}str.erase(8, 2);}str.erase(6, 2);}str.erase(4, 2);}str = "";}}
public:Order(string a, string b, string c, string d, string e, string f)//构造函数直接调用{init();work = f;convMin(a);convHour(b);convDay(c);convMon(d);convWek(e);getAns();}
};
int main()
{ans.clear();int n;cin>>n>>sttime>>edtime;string a, b, c, d, e, w;for(int i = 0; i < n; i++){cin>>a>>b>>c>>d>>e>>w;Order *ord = new Order(a, b, c, d, e, w);}sort(ans.begin(), ans.end(), cmp);//给所有合法指令集按时间排序。for(int i = 0; i < ans.size(); i++){cout<<ans[i].time<<" "<<ans[i].work<<endl;}return 0;
}

 

  相关解决方案