[lnsyoj2232]永恒
题意
给定一个由小写字母和数字组成的字符串 ,给定 个模式串 ,对第 个字符串 ,使得字符串 满足:删除其中任意多个字符,使 形式为 T
+ Date
,其中,T
为模式串 ,Date
为任意一个真实存在的日期。求对于每一个 ,求满足条件的 的个数的和
赛时 70PTS
由于我们要让 尽可能靠前,Date
尽可能靠后,因此我们可以先扫描出 的末尾位置 ,然后枚举所有可能的日期(日期可以预处理),判断哪个日期存在于 后的数字串中。
日期预处理
我们可以提前手打出每个月的天数,然后分别枚举月份和日期,并将月份和日期拼接起来,组合成一个 MMDD
形式的日期,最后存储起来。
赛后
参考赛时的思路,我们需要一种快速的方法查找出 和判断是否有某个日期存在。
由于只需要找到位置就可以了,所以我们可以预处理出一个二维数组 ,表示第 个字符后面的第一个字符 的位置,若不存在则为 ,特别地, 表示第一个字符 的位置。
这个数组可以从后面开始递推:显然 的值一定为 。当枚举到第 项时,显然, 的值为 ,而 值为 ,可以递推。
当我们查找 时,我们就可以从 开始向后查找,时间复杂度就被压缩到了
但我们无法在每一个 中都进行一次合法日期的枚举,因此,我们仍需要预处理这一段。由赛时思路得,Date
应尽可能靠后。因此,我们提前枚举出所有合法日期的开头最靠后的位置,并记录下每个位置的合法日期的个数(每个日期只计算一次)。这样,只需要一个后缀和就可以 的查询所有合法的 Date
了。
为了快速的枚举,我们需要另一个二维数组 ,表示第 个字符前面的第一个字符 的位置,若不存在则为 ,特别地, 表示最后一个字符 的位置。由于定义是和 完全相反的,因此预处理方式也与 完全相反,这里不再赘述。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N = 100005;
int days[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int T;
int n, m;
vector<string> dates;
string s, name;
int ne[N][128];
int pre[N][128];
int sum[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
for (int i = 1; i <= 12; i ++ )
for (int j = 1; j <= days[i]; j ++ ){
string date = " ";
date[0] = i / 10 + '0';
date[1] = i % 10 + '0';
date[2] = j / 10 + '0';
date[3] = j % 10 + '0';
dates.push_back(date);
}
cin >> T;
while (T -- ){
memset(sum, 0, sizeof sum);
cin >> n >> m;
cin >> s;
s = ' ' + s;
memset(ne[m], -1, sizeof ne[m]);
for (int i = m - 1; i >= 0; i -- ){
for (int j = 0; j < 128; j ++ )
ne[i][j] = ne[i + 1][j];
ne[i][s[i + 1]] = i + 1;
}
memset(pre[1], -1, sizeof pre[1]);
for (int i = 2; i <= m + 1; i ++ ){
for (int j = 0; j < 128; j ++ )
pre[i][j] = pre[i - 1][j];
pre[i][s[i - 1]] = i - 1;
}
for (string date : dates){
int j = m + 1;
for (int k = date.size() - 1; k >= 0 && j != -1; k -- ) j = pre[j][date[k]];
if (j != -1) sum[j] ++ ;
}
for (int i = m; i; i -- ) sum[i] += sum[i + 1];
int ans = 0;
for (int i = 1; i <= n; i ++ ){
cin >> name;
int j = 0;
for (int i = 0; i < name.size() && j != -1; i ++ ) j = ne[j][name[i]];
ans += sum[j];
}
cout << ans << '\n';
}
return 0;
}
分类:
题解 / 2024赛时
标签:
基础算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现