题意
苟狗定义了一种新式字符串,只有掌握了这种字符串的构造方法,才可以避免宇宙射线的打击。
新式字符串定义如下:
1.长度为偶数(可以为空)
2.每一个奇数位置的字符都不等于它后面的那个字符
例如,字符串 good、string、xyyx 都符合要求,而字符串 bad、aa、aabc 则不符合。
现在你获得了一个字符串 S,你需要从该字符串中删除最少的字符数,使其变成一个新式字符串,否则你就会受到宇宙射线的打击,众所周知宇宙射线是降智射线。
那么你能够避开宇宙射线吗?
Input
一个行给定一个整数 N(1 <= N <= 200000),表示字符串 S 的长度。
第二行给定长度为 N 且仅包含小写字母的字符串 S。
Output
第一行输出一个数 K(0 <= K <= N),表示需要从 S 中删除的最少的字符数量。
第二行输出删除后的字符串 S。如果为空,你可以输出一个空字符串或者什么都不输出。
输入样例
4
good
4
aabc
3
aaa
输出样例
0
good
2
ab
3
提示
分析
- 题目分析
这道题不难,但是同样的可能也是有点不好理解。至少我是没有理解到的👋
这道题其实需要将原字符串复制到新字符串中,但是在复制过程中进行筛选,使得新字符串一定满足题目要求。
题目要求,
- 字符串长度为偶数
- 字符串中的奇数位置字符与后一个字符不等
注意此处的要求是针对新复制的字符串,因此奇数位置指的是在新字符串中的位置,而不是选定字符在原字符串中是否是奇数位置。而偶数长度指的也是新字符串,而不是原字符串的长度。
因此,解决方法是:
- 遍历原字符串,记录当前新字符串中待加入字符的位置。
- 若当前遍历字符要加入在新字符串中的偶数位置,则说明对该字符无任何要求,因此可以直接加入
- 若加入在新字符串的奇数位置,则需要判断:若该字符在原字符串中的下一个字符和它不一样,则说明这个字符可以直接加入(因为下一个字符一定是加入到新字符串的偶数位置,所以这个字符一定会被添加,因此在新字符串中这两个字符不能相等);反之,则这个字符不能被加入到新字符串的当前奇数位置。
总结
- 确实不大懂,而且其实不大明白为什么这样就保证减少的字符数最少
代码
//
// main.cpp
// lab5
//
//
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
vector<char> output;
int main()
{
ios::sync_with_stdio(false);
int n = 0;
string s;
cin>>n>>s;
int j = 1; //当前字符在新字符串中的位置序号
for( int i = 0 ; i < n - 1 ; i++ ) //遍历原字符串中除最后一个字符外的所有字符
{
// cout<<i<<" i "<<j<<" j "<<s[i]<<endl;
if( j % 2 == 0 ) //如果当前字符在新字符中是偶数位置,则可以直接放入(没有限制)
{
output.push_back(s[i]);
j++; //新字符位置序号+1
}
else //若在新字符串中是奇数个,则需要判定
{
//因为它的在原字符串的下一个一定会被放入到新字符串中,因此当前字符一定不能和下一个字符相等
if( s[i] != s[i + 1] )
{
output.push_back(s[i]); //不相等则可以放入
j++;
}
}
}
//若所得新字符串是奇数个,则最后一个必须放入,否则可以不用放入
//若所得是奇数个,则在之前最后放入的那个字符一定已经判定过和其后一个字符不同,所以最后一个字符可以直接放入
//否则的话到此为止只有偶数个
if( output.size() % 2 != 0 )
output.push_back(s[n - 1]);
cout<<n - output.size()<<endl; //字符串长度差即为去掉字符个数
for( int i = 0 ; i < output.size() ; i++ ) //输出
cout<<output[i];
cout<<endl;
return 0;
}