PAT A1112 Stucked Keyboard【好模拟】⭐⭐⭐⭐⭐

题目描述

在这里插入图片描述

知识点

STL的使用,map的使用

实现

码前思考

  1. 我原来想着是读取当前字符,然后再遍历其后面k个,后来想想这时间复杂度会很高,所以我想到怎么变成 O ( N ) O(N) O(N),于是我就想到了pre这个变量来存储上一个字符,cnt变量来存储上一个字符匹配的长度。妙呀;
  2. 由于使用了pre,我们应该注意到对于第一个字符,它没有pre。这个问题好办,直接初始化即可!
  3. 对于最后一个字符,它没有next,所以它无法被判断;这个问题我一开始忽视了,得在后面加个虚拟字符“#”,OK!
  4. 对于字符串匹配的题目,我们发现好像经常前后加“#”。

代码实现

#include "bits/stdc++.h"
#include <unordered_map>
using namespace std;

const int maxn = 1010;

//用于存储可能stcked的字符 
unordered_map<char,int> mp;
int k;
char str[maxn];
bool sureNoBroken[256]; 
 
int main(){
	fill(sureNoBroken,sureNoBroken+256,true);
	scanf("%d",&k);
	scanf("%s",str);
	
	//当前读取的位置 
	int pos=0;
	int len = strlen(str);
	//为了确保最后一个字符也被考虑到! 
	str[len] = '#';
	char pre = str[pos];
	int cnt = 1;
	pos++;
	
	while(pos<=len){
		//首先判断与前一个字符是否相同
		char cur = str[pos];
		if(pre == cur){
			cnt++;
			//如果cnt达到了k
			if(cnt == k && sureNoBroken[pre] == true){
				mp[pre]++;
				//重新设置pre和cnt
				if(pos==len-1){
					break;
				}else{
					pos++;
					pre = str[pos];
					cnt = 1; 	
				} 
			}
		}else{
			//说明不相同,那么这个数一定不是重复的,那么考虑是否要移除map
			if(mp.count(pre) != 0){
				mp.erase(pre);
			}
			sureNoBroken[pre] = false;
			cnt = 1;
			pre = cur; 
		}
		pos++; 			
	}
	//接下来开始重新组合字符串
	//存储的输出字符的数组
	char output[maxn];
	//输出的长度 
	int i=0;
	//输出字符的下标 
	int j=0;
	
	unordered_map<char,int> mp2;
	
	while(j < len){
		//如果这个字符在mp里面
		char cur = str[j];
		if(mp.count(cur) != 0){
			if(mp2.count(cur) == 0){
				printf("%c",cur);
				mp2[cur] = 1;
			}
			output[i] = cur;
			j += k;
		}else{
			output[i] = cur;
			j++;
		}
		i++;	 
	} 
	
	printf("\n");
	
	for(int k=0;k<i;k++){
		printf("%c",output[k]);
	} 
	 
	return 0;
} 

码后反思

  1. 我一开始写错,对于我没有判断下面这种情况:

    3
    88___iia___999888
    

    上述的8应该不是的!
    后来看了柳神的题解,才加了一个sureNoBroken[256]数组,这个字符数组用的很妙!以后要会这样用!256标识ASCII码最大值。

二刷代码

#include "bits/stdc++.h"
#include <unordered_map>
using namespace std;

const int maxn = 1010;

//用于存储可能stucked的字符
unordered_map<char,int> mp;
int k;
char str[maxn];
bool sureNoBroken[256];

int main(){
	fill(sureNoBroken,sureNoBroken+256,true);
	scanf("%d",&k);
	scanf("%s",str);
	
	//当前读取的位置
	int pos=0;
	int len=strlen(str);
	//为了确保最后一个字符被考虑到
	str[len]='#';
	char pre=str[pos];
	int cnt=1;
	pos++;
	
	while(pos<=len){
		//首先判断与前一个字符是否相等
		char cur = str[pos];
		if(pre==cur){
			cnt++;
			//如果cnt达到了k
			if(cnt==k && sureNoBroken[pre]==true){
				mp[pre]++;
				//重新设置pre和cnt
				pos++;
				pre=str[pos];
				cnt=1;
			}
		}else{
			//说明不相同,那么这个数一定不是重复的,那么考虑是否移除
			if(mp.count(pre)!=0){
				mp.erase(pre);
			}
			sureNoBroken[pre]=false;
			cnt=1;
			pre=cur; 
		}
		pos++;  
	}
	
	//接下来是重新组合字符串
	//存储输出字符的数组
	char output[maxn];
	//输出长度
	int i=0;
	//输出字符的下标
	int j=0;
	
	unordered_map<char,int> mp2;
	
	while(j<len){
		char cur = str[j];
		if(mp.count(cur)!=0){
			if(mp2.count(cur)==0){
				printf("%c",cur);
				mp2[cur]=1;
			}
			output[i]=cur;
			j+=k;
		}else{
			output[i]=cur;
			j++;
		}
		i++;
	}
	
	printf("\n");
	
	for(int k=0;k<i;k++){
		printf("%c",output[k]);
	} 
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值