题目链接https://pintia.cn/problem-sets/994805342720868352/problems/994805357933608960
一开始没搞懂题意,以为是一个键坏了那么按出来的次数就大大于等于k
,后来才发现原来如果坏了应该是k
的整数倍
难点在于,即使刚开始碰到某个字母出现次数等于k
,也不能判断它的键是否坏了,因为如果之后又出现这个字母并且次数小于k
,那么说明这个键是好的。之前连续打出k
个只是巧合。
因此应该一开始假定所有键都是坏的,然后根据扫描情况,确定哪些键是好的。
把键分成前面一部分和最后k-1
个,那么后一部分的字母,如果不是前面一部分的字母的重复,就不可能是坏掉的键。
而前面一部分的字母正常去判断,如果出现次数小于等于k
,那么就是好键。如果可能是坏键,那么将指针移过k
个距离。
完整代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
using namespace std;
int char2num(char c) {
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'a' && c <= 'z')
return c - 'a' + 10;
else
return 36;
}
int main() {
int k;
string str;
scanf("%d\n", &k);
getline(cin, str);
vector<bool> isStk(37, true);
vector<bool> known(37, false);
int i;
for (i = 0; i <= str.size() - k; i++) {
bool flag = true;
for (int j = 1; j < k; j++) {
if (str[i+j] != str[i]) {
flag = false;
break;
}
}
if (flag)
i += k-1;
else
isStk[char2num(str[i])] = false;
}
while (i < str.size())
isStk[char2num(str[i++])] = false;
for (i = 0; i < str.size(); i++) {
int num = char2num(str[i]);
if (isStk[num] && !known[num]) {
known[num] = true;
cout << str[i];
}
}
cout << endl;
for (i = 0; i < str.size(); i++) {
int num = char2num(str[i]);
if (isStk[num]) {
i += k - 1;
cout << str[i];
}
else
cout << str[i];
}
return 0;
}