PAT甲级1112.

目录

A1112

题目

样例

输入:

3
caseee1__thiiis_iiisss_a_teeeeeest

输出:

ei
case1__this_isss_a_teest

补充样例

输入:

3
caseeeaaa1__thiiisa_iiisss_a_aaaaaateeeeeest

输出:

ei
caseaaa1__thisa_isss_a_aaaaaateest

思路和坑点

  思路:
  这个题目的问题在于如何准确辨别坏键,即理解坏键的情况,根据示例可知必须是每次都出现了连续k个或者k的整数倍个字符的才算做是坏键,因此需要对连续出现的字符进行计数并进行判定即可。因此需要计数器统计连续字符,还需要有一个Table来标记坏键,这里可能出现误判的情况,比如序列的前部分和后部分都出现了k整数倍的字符串,但是中间出现了非k整数倍的情况,说明这个键是好的(补充样例中的字符a就不是坏键,理解起来好理解,但是程序来判定上需要注意逻辑实现的时候不要漏掉),那么此处需要注意好键的标记优先级高于坏键,具体可以参考代码实现部分的注释说明。
  坑点:
  主要在于坏键和连续出现的好键之间的区分和判定。

AC代码

#include<bits/stdc++.h>
using namespace std;
int main(){    
#ifdef ONLINE_JUDGE    
#else    
    freopen("1.txt", "r", stdin);    
#endif    
    int n;
    map<char,int> mp;                           //标识键是否损坏 ,1表示正常,2表示坏键 (最好不使用true和false,因为判定时,不存在的map键值为0,即false,影响判定) 
    string wrong="",real="",str;                //wrong存放可疑的坏键,real真正的输出字符串,str用于存放读入的字符串
    cin>>n>>str;
    str+="E";                                   //为了结尾处的判定能够写在循环内,在末尾加上一个不属于统计范围的字符
    int cnt=1;                                  //统计重复次数,初始化为1; 
    for(int i=1;i<str.size();i++){              //从第二个字符开始,第一个字符默认统计在内,个数为cnt的初始值1 
        if(str[i]==str[i-1])                    //如果与前一个字符相同,表示连续,cnt++ 
            cnt++;
        else{                                   //否则判定是否是坏键 
            if(cnt%n!=0)                        //如果不是整数倍,则证明是好键 
                mp[str[i-1]]=1;                 //好键可以覆盖误判的坏键标记,如果前面出现过一次整数倍,后边出现了不是整数倍,说明前边坏键判定不正确,需要修正 
            else{
                if(mp.find(str[i-1])==mp.end())
                    wrong.push_back(str[i-1]);  //当前的键被怀疑是坏键,则加入可疑坏键序列。其中可以坏键不要重复添加
                if(mp[str[i-1]]!=1)
                    mp[str[i-1]]=2;             //确定时坏键的时候需要优先判定是不是好键,如果已经提前被标记为好键,则此时进入坏键判定为后边整数倍序列误判所致 
            }
            cnt=1;                              //更新计数器
        }
    }
    cnt=1;                                      //最终完全确定坏键以后,遍历统计一遍,对于重复的字符,如果是正常重复就输出cnt个,否则输出cnt/n个 
    for(int i=1;i<str.size();i++){
        if(str[i]==str[i-1])                    //连续部分进行计数
            cnt++;
        else{
            if(mp[str[i-1]]==1)                 //如果是好键,正常重复cnt个
                for(int j=0;j<cnt;j++)
                    real+=str[i-1];
            else
                for(int j=0;j<cnt/n;j++)        //如果是坏键,需要除以卡键次数
                    real+=str[i-1];
            cnt=1;                              //更新计数器
        }
    }
    for(int i=0;i<wrong.size();i++){            //输出坏键 
        if(mp[wrong[i]]==2)
            putchar(wrong[i]);
    }
    cout<<'\n'<<real;                           //输出真实的字符串 
    return 0;    
}