C. Did We Get Everything Covered?
C. Did We Get Everything Covered?
You are given two integers and along with a string .
Your task is to check whether all possible strings of length that can be formed using the first lowercase English alphabets occur as a subsequence of . If the answer is NO, you also need to print a string of length that can be formed using the first lowercase English alphabets which does not occur as a subsequence of .
If there are multiple answers, you may print any of them.
Note: A string is called a subsequence of another string if can be obtained by deleting some (possibly zero) characters from without changing the order of the remaining characters.
Input
The first line of input contains a single integer , the number of test cases.
The first line of each test case contains integers , where and are the same as described in the input and is the length of the string .
The second line of each test case contains a single string of length , comprising only of the first lowercase English alphabets.
It is guaranteed that the sum of and the sum of over all test cases does not exceed .
Output
For each test case, print YES if all possible strings of length that can be formed using the first lowercase English alphabets occur as a subsequence of , else print NO.
If your answer is NO, print a string of length that can be formed using the first lowercase English alphabets which does not occur as a subsequence of in the next line.
You may print each letter of YES or NO in any case (for example, YES, yES, YeS will all be recognized as a positive answer).
Example
input
3
2 2 4
abba
2 2 3
abb
3 3 10
aabbccabab
output
YES
NO
aa
NO
ccc
Note
For the first test case, all possible strings (aa, ab, ba, bb) of length that can be formed using the first English alphabets occur as a subsequence of abba.
For the second test case, the string aa is not a subsequence of abb.
解题思路
受 A 题 We Got Everything Covered! 的启发,如果将前 个字符构成一组,并把至少 组拼接成字符串,那么字符串所有的子序列一定包含 种由前 个字符构成的长度为 的串。不过这只说明了充分性,并不能说明必要性,即如果某字符串所有的子序列包含由前 个字符构成的长度为 的串,则该字符串一定至少包含 个由前 个字符构成的组。比赛的时候没想到也没去猜所以没做出来。
事实上这个必要性是成立的。我们依次找到 中由前 个字符构成的组,即依次遍历 的每个字符,用一个哈希表记录某个字符是否出现过,以及一个变量 统计当成组中有多少种字符。当遍历到 ,哈希表的 处记为 ,如果在变化之前为 则 加 。如果此时的 ,说明已经找到一组,清空哈希表和 继续找下一组。
如果我们每次都选择每组中最后一个字符来尝试构成一个反例,显然如果字符串中小于 组,那么就一定可以构造出一个反例,只需将最后一组中没出现过的字符填到反例后面直到长度变成 。这种构造方案也证明了必要性。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1010;
char s[N];
bool vis[26];
void solve() {
int n, m, k;
scanf("%d %d %d %s", &n, &k, &m, s);
string ans;
memset(vis, 0, sizeof(vis));
for (int i = 0, c = 0; i < m; i++) {
if (!vis[s[i] - 'a']) c++;
vis[s[i] - 'a'] = true;
if (c == k) {
ans.push_back(s[i]);
memset(vis, 0, sizeof(vis));
c = 0;
}
}
if (ans.size() >= n) {
printf("YES\n");
}
else {
printf("NO\n");
for (int i = 0; i < 26; i++) {
if (!vis[i]) {
while (ans.size() < n) {
ans.push_back('a' + i);
}
printf("%s\n", ans.c_str());
return;
}
}
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round 921 (Div. 1, Div. 2) Editorial:https://codeforces.com/contest/1925/problem/C
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18004970
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效