首页 > 其他分享 >CF600C题解

CF600C题解

时间:2022-09-30 18:00:18浏览次数:77  
标签:字符 输出 int 题解 偶数 字符串 CF600C 回文

题意

有一串字符串 \(S\),设改变 \(S\) 中的任意一个字符称为 1 次转变(交换任意 2 个字符不算转变次数),求在操作最少的情况下可得到的回文字符串

正文

♦ 算法:找规律
♦ 准备知识:桶排序

对于一个回文串,有两种情况:

  1. 回文串字符数为偶数,如 assddssa,易得其中每种字符数量都是偶数。

  2. 回文串字符数为奇数,如 asdfdsa,易得其中除了最中间的字符数量为奇数,其余都是偶数。

再想到排序是不算转变次数的,很容易想到桶排序。

将 \(S\) 中的每个字符对应的桶加 1,通过上述规律可以知道,每个为偶数的桶不需要转变,每个为奇数的桶执行以下操作:

去掉一个字符使桶为偶数,将去除的字符留下备用,而接下来就是对这些字符进行转变,见例子。

字符串:
aesdffdaa
桶排后:
31122
aesdf
操作后的桶:
20022
aesdf
剩余字符:
aes

设剩下的字符按字典序排序后组成的字符串为 \(B\),长度为 \(a\)。

  1. 若 \(a\) 为偶数,则将靠后的字符变成靠前的字符,由于要使转变次数最少,容易发现一个方法:令 \(B_i\) 和 \(B_{a-i+1}\) 配对,将 \(B_{a-i+1}\) 变成 \(B_i\),最后把获得的字符串加入桶,按照字典序输出。这可以在最少次数的转变下将 \(S\) 变成一个字典序最小的回文串。

  2. 若 \(a\) 为奇数,方法和上一个差不多,只对最中间的字符不操作并保存即可。

当然,可能会有人对 2 有疑惑,为什么不选择排头的字符或末尾的呢?

请看(红名请略过):

字符串:
asdfghgfd
桶排后:
112221
asdfgh
剩余字符(按字典序排):
ahs
若选择排头:
 转换:ahh
 回文串:dfghahgfd
若选择末尾:
 转换:aas
 回文串:adfgsgfda
若选择中间:
 转换:aha
 回文串:adfghgfda

很显然,选中间所得的回文串字典序更小

输出是这样的:

  1. 若回文串长度为偶数,由于回文串是先后对应的,只需要在所有桶中先从头到尾输出一半,再从尾到头输出剩下的即可。

  2. 若为奇数,先在所有桶中从头到尾输出一半,再输出中间的字符,最后再从头到尾输出剩下的即可。

理论讲了一大堆,上代码:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int c[205],num;
queue<char>q;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	char a;
	while(cin>>a){
		++c[a];//桶排
	}
	for(int i=1;i<=200;++i){
		if(c[i]%2==0)	continue;//若为偶数,略过
		++num;//统计字符串长度
		q.push(i);//若为奇数,保存
		//由于所有桶是按字典序排的,所以保存的字符也是按字典序排列的
		//队列的特性
	}
	
	if(num%2==0){//其实无需计算设下的字符数,易得若S长度为偶数,则剩下的字符数也是偶数
		for(int i=1;i<=num/2;i++){
			c[q.front()]+=2;//将靠后的转变为靠前的,并加入桶
			q.pop();
		}
		for(int i=1;i<=200;++i){
			for(int j=1;j<=c[i]/2;j++){
				cout<<(char)i;//输出
			}
		}
		for(int i=200;i>=1;--i){
			for(int j=1;j<=c[i]/2;j++){
				cout<<(char)i;
			}
		}
		return 0;
	}
	else{
		for(int i=1;i<=num/2;i++){
			c[q.front()]+=2;
			q.pop();
		}
		for(int i=1;i<=200;++i){
			for(int j=1;j<=c[i]/2;j++){
				cout<<(char)i;
			}
		}
		cout<<q.front();//输出中间的
		for(int i=200;i>=1;--i){
			for(int j=1;j<=c[i]/2;j++){
				cout<<(char)i;
			}
		}
		return 0;
	}
}//撒花

提交记录,华丽结束。

后附

日志

v1.0 on 2022.09.30: 发布

蒟蒻的话

这么良心的博主,怎么不点赞呢?

标签:字符,输出,int,题解,偶数,字符串,CF600C,回文
From: https://www.cnblogs.com/wanguan/p/16745745.html

相关文章

  • 题解 [POI2010]ZAB-Frog
    很厉害的题。倍增和单调队列。这是zpl新手向算法第二弹,第一弹可以看小挖的核燃料填充我会尽量讲的比较细致。同第一弹,尽量配合代码食用。这道题的题目描述写的不是......
  • useState"失效“问题解释和解决方案
    示例:const[count,setCount]=useState(0)简单的onclick事件中,setCount(1)后紧接着输出或者使用,则输出的值还是0原因:setState会导致页面刷新,(useRef不会)页面刷新的时候......
  • 【题解】P2167 [SDOI2009]Bill的挑战(状压 DP)
    【题解】P2167[SDOI2009]Bill的挑战挺好的一道状压DP。可惜我脑子有病。()题目链接P2167[SDOI2009]Bill的挑战](https://www.luogu.com.cn/problem/P3225)题意概述......
  • 13.56M系列芯片-SI522/SI522A/SI523/ FMI7522 /FMI7550 /RC522芯片常见问题解答
    13.56M系列芯片-标配版:SI522/SI522A/SI523的几款芯片会遇到的一些常见问题解答:SI522和SI522A的异同点?SI522A为SI522的升级版本,SI522A增加了ACD工作模式,其他均相同。标配......
  • LG4381 [IOI2008] Island 题解
    LG4381[IOI2008]Island给定一个基环树森林,求每棵基环树的直径长度和。直径是基环树上最长的一条简单路径。题目保证树边的方向构成了一颗内向树。题解先简单说一下......
  • -bash: ./start.sh: /bin/bash^M: bad interpreter问题解决
    出现上面错误的原因是脚本文件是DOS格式,即每一行的行尾以\r\n来标识,使用vim打开脚本,运行::setff?显示fileformat=dos,就是说格式不兼容,在Unix下运行脚本会提示该错误。......
  • 关于multi-statement not allow问题解决
    出现这个问题是因为druid有一个防火墙,默认是不允许批量操作的,目的应该是防止sql注入等风险。如果你在url中设置了allowMultiQueries=true允许批量操作。那么你的配置应该......
  • Redis(六)应用问题解决
    第一章缓存穿透1.1问题描述key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用......
  • mac zsh: command not found: adb 问题解决
     问题:mac终端提示:zsh:commandnotfound:adb 第一步查看~/.bash_profile的配置是否配置得了AndroidSDK执行命令open ~/.bash_profile  可见存在该配置第二步执行......
  • 洛谷P8551 Bassline 题解
    P8551Bassline题解分析这道题做月赛的时候想了好久,最后发现其实很简单。我们用样例数据来分析:如图所示,我们将每个区间抽象化为一个一个的长条。题目给我们的两个要......