题目描述
知识点
STL的使用,map的使用
实现
码前思考
- 我原来想着是读取当前字符,然后再遍历其后面k个,后来想想这时间复杂度会很高,所以我想到怎么变成
O
(
N
)
O(N)
O(N),于是我就想到了
pre
这个变量来存储上一个字符,cnt
变量来存储上一个字符匹配的长度。妙呀; - 由于使用了
pre
,我们应该注意到对于第一个字符,它没有pre
。这个问题好办,直接初始化即可! - 对于最后一个字符,它没有
next
,所以它无法被判断;这个问题我一开始忽视了,得在后面加个虚拟字符“#”,OK! - 对于字符串匹配的题目,我们发现好像经常前后加“#”。
代码实现
#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;
}
码后反思
-
我一开始写错,对于我没有判断下面这种情况:
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;
}