1

题目大意

给定k和一个字符串s,由于一些键盘的按键损坏,损坏的键按一下会重复出现k次,要求你找出所有的坏件和原始输入字符串。

算法思路

一个键是坏键的前提是该字符每一次连续出现的次数一定是k的整数倍,那么我们可以先采用hasShownNotStucked哈希表记录那些一定是好键的字符,又由于坏键只记录一次就好,所以使用hasShownStucked记录记录已经出现过并确定是坏键的按键,避免重复添加。我们采用两边遍历的方式进行求解

第一次遍历将所有一定是好键的字符全部记录,具体做法就是比较当前字符和后一字符是否相等,如果不等那么一定不是坏键,否则统计其出现的次数cnt,只要当前字符没有确定为好键并且cnt%n!=0,那么就说明该键为好键。

第二次遍历进行获取重复的字符组成的字符串repeated和原始字符串origin,具体做法就是,如果当前字符一定是好键,那么就添加进origin中,否则就得计算出现的次数cnt,并让origin添加cnt/n个s[i],判断当前字符是否已经记录为坏键,如果没有就记录该坏键并添加该字符到repeated中。

注意点

  • 1、一个键有可能之前出现k的整数倍次,但是最后出现的次数不能整除k,那么就说明不是坏键,比如k=3,s=eeerre,其中e就是好键,所以需要先遍历一遍将所有一定是好键的键进行记录。

提交结果

image.png

AC代码

#include<cstdio>
#include<iostream>
#include<unordered_map>

using namespace std;

unordered_map<char,bool> hasShownNotStucked;// 记录好键
unordered_map<char,bool> hasShownStucked;// 记录已经出现过并确定是坏键的按键

int main() {
    int n;
    scanf("%d",&n);
    string s;
    cin>>s;
    string repeated,origin;
    int i;
    // 第一次遍历记录所有一定不是坏键的键
    for(i=0;i<s.size()-1;){
        if(s[i]!=s[i+1]){
            // 当前按键只出现了一次,一定不是坏键
            hasShownNotStucked[s[i]] = true;
            ++i;
        }else{
            // 统计出现重复的次数
            int cnt = 0;
            for(int j=i;j<s.size();++j){
                if(s[j]==s[i]){
                    ++cnt;
                }else{
                    break;
                }
            }
            if(!hasShownNotStucked[s[i]]&&cnt%n!=0){
                // 当前字符之前不确定,但是无法整除n说明一定不是坏键
                hasShownNotStucked[s[i]] = true;
            }
            i += cnt;
        }
    }
    if(i<s.size()){
        // s[i]!=s[i+1],说明最后一个键也不是坏键
        hasShownNotStucked[s[i]] = true;
    }
    for(i=0;i<s.size();){
        if(hasShownNotStucked[s[i]]){
            // 一定不是坏键
            origin += s[i++];
        }else{
            // 有可能是坏键
            // 统计出现重复的次数
            int cnt = 0;
            for(int j=i;j<s.size();++j){
                if(s[j]==s[i]){
                    ++cnt;
                }else{
                    break;
                }
            }
            // 重复添加cnt/n个s[i]
            int a = cnt/n;
            while(a--){
                origin += s[i];
            }
            if(!hasShownStucked[s[i]]){
                // 之前没有添加过该重复字符
                hasShownStucked[s[i]] = true;
                repeated += s[i];
            }
            i += cnt;
        }
    }
    cout<<repeated<<endl<<origin;
    return 0;
}

乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得