PAT (Advanced Level) Practice 1112 Stucked Keyboard (20分) (基础不扎实的后果)

1.题目

On a broken keyboard, some of the keys are always stucked. So when you type some sentences, the characters corresponding to those keys will appear repeatedly on screen for k times.

Now given a resulting string on screen, you are supposed to list all the possible stucked keys, and the original string.

Notice that there might be some characters that are typed repeatedly. The stucked key will always repeat output for a fixed k times whenever it is pressed. For example, when k=3, from the string thiiis iiisss a teeeeeest we know that the keys i and e might be stucked, but s is not even though it appears repeatedly sometimes. The original string could be this isss a teest.

Input Specification:

Each input file contains one test case. For each case, the 1st line gives a positive integer k (1<k≤100) which is the output repeating times of a stucked key. The 2nd line contains the resulting string on screen, which consists of no more than 1000 characters from {a-z}, {0-9} and _. It is guaranteed that the string is non-empty.

Output Specification:

For each test case, print in one line the possible stucked keys, in the order of being detected. Make sure that each key is printed once only. Then in the next line print the original string. It is guaranteed that there is at least one stucked key.

Sample Input:

3
caseee1__thiiis_iiisss_a_teeeeeest

Sample Output:

ei
case1__this_isss_a_teest

2.题目分析

我的思路是将字符大概分类三种:一直满足;先满足后不满足;先不满足后满足

使用mark标记字符:1为正常字符,2为所求的重复字符

开始没用mark,用的unordered_set,我一直不知道unordered_set、unordered_map只是保证不进行排序,但是不保证输入的顺序就是输出的顺序,于是错错错错错错N次

这里用了vector来存放重复字符,而vector的删除也很有说法:

参考(https://blog.csdn.net/ww1473345713/article/details/92801632?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

比如,有一个vector<int> nums = {1, 2, 2, 2, 2, 3, 5},要求删除nums中所有值为2的元素。C++初学者可能很快就写出代码:

for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++) {
    if (*it == 2) {
        nums.erase(it);
    }
}

这段代码循环遍历nums中的每个元素,判断是否为2,是的话则erase掉。看起来好像没什么问题,但是实际上已经造成了bug。这段代码的执行完成后,nums存储的元素是{1, 2, 2, 3, 5},值为2的元素并没有被全部清除掉

原因就是迭代器失效:在第一个2被erase掉的时候,it迭代器已经失效了,用它来继续遍历vector就会漏掉被删除元素后面的第一个元素,导致2没有被完全清除。

正确方法:

for (vector<int>::iterator it = nums.begin(); it != nums.end();) {
    if (*it == 2) {
        it = nums.erase(it);//注意这里!!
    } else {
        ++it;
    }
}

 3.代码

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int mark[200];
int main()
{
	int k;
	string list;
	scanf("%d", &k);
	cin >> list;
	vector<char>out;
	for (int i = 0; i < list.length(); i++)
	{
		int amount = 0;
		for (int j = i; j < list.length() && list[i] == list[j]; j++)
			amount++;
		if (amount != 0 && amount%k == 0) 
		{
			i += amount-1;
			if (mark[list[i]] == 0)
			{
				out.push_back(list[i]);
				mark[list[i]] = 2;
			}
		}
		else
		{
			mark[list[i]] = 1;
			for (auto temp = out.begin(); temp != out.end(); )
			{
				if (*temp == list[i])temp=out.erase(temp);
				else temp++;
			}
		}
	}
	for (auto it = out.begin(); it != out.end(); it++)
		printf("%c", *it);
	printf("
");
	for (int i = 0; i < list.length(); i++)
	{
		if (mark[list[i]]==2)
			i += (k-1);
		printf("%c", list[i]);
	}
}

原文地址:https://www.cnblogs.com/Jason66661010/p/12788858.html