题目大意
给定的字符串中,有几个子序列是 2023 2023 2023 年的日期(每个日期只能算一次)。
法一
枚举所有长度为 8 8 8 的子序列,判断是否是有效日期并去重,时间复杂度 O ( C 100 8 ) O(C^8_{100}) O(C1008)。
法二
枚举所有日期,判断是否存在对应子序列,时间复杂度 O ( 365 × 100 ) O(365\times100) O(365×100)。
法二明显优于法一,不仅效率更高,代码也更容易完成。
具体步骤如下:
- 日期相关函数,用于枚举
2023
2023
2023 年的所有日期,由于
2023
2023
2023 年为平年,下文中的
is_leap
函数可以省略。 - 将日期转换为字符串,例如 2023 2023 2023 年 7 7 7 月 2 2 2 日,需要转换为字符串 20230702 20230702 20230702。
- 判断字符串中是否含有日期的子序列,可以用双指针算法实现。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
string str = "5686916124919823647759503875815861830379270588570991944686338516346707827689565614010094809128502533";
int days[] =
{
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
bool is_leap(int y)
{
return y % 400 == 0 || y % 4 == 0 && y % 100 != 0;
}
int daysOfMonth(int y, int m)
{
if (m == 2)
return 28 + is_leap(y);
return days[m];
}
string get(int y, int m, int d)
{
string res = to_string(y);
if (m < 10)
res += "0";
res += to_string(m);
if (d < 10)
res += "0";
res += to_string(d);
return res;
}
bool check(string s)
{
int k = 0;
for (auto c: str)
if (c == s[k])
{
k ++;
if (k == 8)
return true;
}
return false;
}
int main()
{
int y = 2023, m = 1, d = 1;
int res = 0;
while (y < 2024)
{
res += check(get(y, m, d));
d ++;
if (d > daysOfMonth(y, m))
m ++, d = 1;
if (m > 12)
y ++, m = 1;
}
cout << res << endl;
return 0;
}
【在线测评】