C. Did We Get Everything Covered?
You are given two integers $n$ and $k$ along with a string $s$.
Your task is to check whether all possible strings of length $n$ that can be formed using the first $k$ lowercase English alphabets occur as a subsequence of $s$. If the answer is NO, you also need to print a string of length $n$ that can be formed using the first $k$ lowercase English alphabets which does not occur as a subsequence of $s$.
If there are multiple answers, you may print any of them.
Note: A string $a$ is called a subsequence of another string $b$ if $a$ can be obtained by deleting some (possibly zero) characters from $b$ without changing the order of the remaining characters.
Input
The first line of input contains a single integer $t \, (1 \le t \le 10^5)$, the number of test cases.
The first line of each test case contains $3$ integers $n \, (1 \le n \le 26), \: k \, (1 \le k \le 26), \: m \, (1 \le m \le 1000)$, where $n$ and $k$ are the same as described in the input and $m$ is the length of the string $s$.
The second line of each test case contains a single string $s$ of length $m$, comprising only of the first $k$ lowercase English alphabets.
It is guaranteed that the sum of $m$ and the sum of $n$ over all test cases does not exceed $10^6$.
Output
For each test case, print YES if all possible strings of length $n$ that can be formed using the first $k$ lowercase English alphabets occur as a subsequence of $s$, else print NO.
If your answer is NO, print a string of length $n$ that can be formed using the first $k$ lowercase English alphabets which does not occur as a subsequence of $s$ 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 $2$ that can be formed using the first $2$ 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! 的启发,如果将前 $k$ 个字符构成一组,并把至少 $n$ 组拼接成字符串,那么字符串所有的子序列一定包含 $k^n$ 种由前 $k$ 个字符构成的长度为 $n$ 的串。不过这只说明了充分性,并不能说明必要性,即如果某字符串所有的子序列包含由前 $k$ 个字符构成的长度为 $n$ 的串,则该字符串一定至少包含 $n$ 个由前 $k$ 个字符构成的组。比赛的时候没想到也没去猜所以没做出来。
事实上这个必要性是成立的。我们依次找到 $s$ 中由前 $k$ 个字符构成的组,即依次遍历 $s$ 的每个字符,用一个哈希表记录某个字符是否出现过,以及一个变量 $c$ 统计当成组中有多少种字符。当遍历到 $s_i$,哈希表的 $s_i$ 处记为 $\text{true}$,如果在变化之前为 $\text{false}$ 则 $c$ 加 $1$。如果此时的 $c=k$,说明已经找到一组,清空哈希表和 $c$ 继续找下一组。
如果我们每次都选择每组中最后一个字符来尝试构成一个反例,显然如果字符串中小于 $n$ 组,那么就一定可以构造出一个反例,只需将最后一组中没出现过的字符填到反例后面直到长度变成 $n$。这种构造方案也证明了必要性。
AC 代码如下,时间复杂度为 $O(m)$:
#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
标签:le,string,vis,Did,NO,Everything,length,Covered,first From: https://www.cnblogs.com/onlyblues/p/18004970