0%

csp 201712-3 Crontab (恶心的)string处理 大模拟

题目链接

然后贴上一份别人比我写得好看的代码

不得不说,不提前规划好怎么写,或者不用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中,如果不在去掉。

      代码:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186
      187
      188
      189
      190
      191
      192
      193
      194
      195
      196
      197
      198
      199
      200
      201
      202
      203
      204
      205
      206
      207
      208
      209
      210
      211
      212
      213
      214
      215
      216
      217
      218
      219
      220
      221
      222
      223
      224
      225
      226
      227
      228
      229
      230
      231
      232
      233
      234
      235
      236
      237
      238
      239
      240
      241
      242
      243
      244
      245
      246
      247
      248
      249
      250
      251
      252
      253
      254
      255
      256
      257
      258
      259
      260
      261
      262
      263
      264
      265
      266
      267
      268
      269
      270
      271
      272
      273
      274
      275
      276
      277
      278
      279
      280
      281
      282
      283
      284
      285
      286
      287
      288
      289
      290
      291
      292
      293
      294
      295
      296
      297
      298
      299
      300
      301
      302
      303
      304
      305
      306
      307
      308
      309
      310
      311
      312
      313
      #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;
      }
-------------这么快就看完啦^ω^谢谢阅读哟-------------