P14225 [ICPC 2024 Kunming I] 左移 2 个人题解

题目传送门

题目大意:

给定一个字符串 \(s\),进行一次左移,即使字符串 \(s\) 变为 \(s_{(d+0)\bmod n},s_{(d+1)\bmod n},\cdots,s_{(d+n-1)\bmod n}\),然后求最少更改几个字符可以变成美丽字符串(即使字符串内相邻字符与不相同)。

解题方法:

这道题是一道贪心,我们发现一段连续且字符全都相等的字符串变为美丽字符串需要进行 \(\lfloor \frac{len}{2}\rfloor\) 次更改,我们在进行左移使可以使这样一段连续且字符全都相等的字符串分成两段,注意到向下取整的性质,即相邻的两个数,奇数向下取整是要比偶数向下取整小的,即我们在左移使如果把一段连续且字符全都相等的字符串分为两个长度为奇数的字符串是要比偶数更优的。在实现时我们可以把这样一段字符串左移至第一个字符与最后一个字符不同的位置,然后检查答案就行。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e6+6;
inline int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-')
			f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
} //快读 
int T=read();
char ch[N];
vector<int> ans;
signed main(){
	while(T--){
		scanf("%s",ch);
		int n=strlen(ch);
		int j=0;
		if(ch[0]==ch[n-1]){	//左移使第一个数与最后一个数位置不同 
			for(j=0;j<n;j++){
				if(ch[j]==ch[n-1])
					ch[j+n]=ch[j];
				else
					break;
			}
		}
		if(j==n)//如果这个序列全为一个字符,直接输出n/2 
			printf("%lld\n",n/2);
		else{
			ans.clear();//多测要清空!! 
			int cnt=1;//一个字符也有长度 
			for(int i=j+1;i<=j+n-1;i++){
				if(ch[i]!=ch[i-1]){//如果不再连续,统计答案 
					ans.push_back(cnt);
					cnt=1;//长度清空 
				}
				else
					cnt++;
			}
			ans.push_back(cnt);//把最后一个字符串统计上!! 
			int sum=0;
		 	bool ok=false;
			for(int i=0;i<ans.size();i++){
				sum+=ans[i]/2;//统计答案 
				if(ans[i]%2==0)//如果是偶数,则可以拆分,答案-1 
					ok=true;
			}
			printf("%lld\n",max(sum-ok,0ll));
		}
	}
	return 0;
}
posted @ 2025-11-23 17:35  See_you_soon  阅读(7)  评论(0)    收藏  举报