P8739 [蓝桥杯 2020 国 C] 重复字符串

本文介绍了如何使用贪心策略解决一个编程问题,即判断给定字符串s是否可以转化为n次重复的子序列,通过计算字符频率并进行适当修改,给出最优解。作者通过代码展示了如何遍历子序列,统计字符出现频率并确定所需的修改次数。
摘要由CSDN通过智能技术生成

题目来源:P8739 [蓝桥杯 2020 国 C] 重复字符串 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题一看就是贪心算法,但是我没能看出如何贪心,贪心的地方在哪,故写了这篇博客警示自己。言归正传:

题意描述:给定一段字符串s,在给定一个整数n,判断这个字符串是否可以转化成n次字符串,若能则输出修改字符串s的次数,不能则输出-1。

分析:我们需要先判断字符串可以分解为几段子序列(l=s的长度/n),当s的长度不能整除n时,直接输出-1,若整除则遍历字符串s的一段子序列(由于题目要求所有子序列相同,所以就直接取第一段子序列),然后在里面另开一重循环,循环的变量每次都加上l,用一个数组v来统计字符串中各个字符出现的频率(既然要修改字符,那么我们就先找出字符串s中出现频率最大的字符,将其他字符都修改为这个字符),找出出现频率最大的字符,每次循环都加上n-出现频率最大的字符的个数(将不同于这个字符的其他字符都转化为这个字符),最后输出结果。

代码如下:

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
int v[26];//桶的思维
int ans;
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
	int n;
	string s;
	cin >> n >> s ;
    int l=s.size()/n;//取第一段子序列长度
    if(s.size()%n!=0) cout << "-1" << endl;//当不被整除时则不能拆分为n次字符串
    else{
    	for(int i=0;i<l;++i){//外层循环只需遍历一次子序列即可
    		memset(v,0,sizeof v);
    		int maxn=0;
    		for(int j=i;j<s.size();j+=l){//内层循环的循环遍量每次加上l,每隔l个长度,将字符放入桶中
    			v[s[j]-'a']++;
			}
			for(int i=0;i<26;++i) maxn=max(maxn,v[i]);//找出单个字符出现最高的频率
			ans+=n-maxn;//当都是这个字符时,那n-maxn都为0,则不需要变动,反之则加上需要变动的次数
		}
		cout << ans << endl;
	}
	return 0;
} 

  • 22
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
题目描述: 给定一个字符串s,求出该字符串的最长重复子串长度。 输入格式: 第一行为一个整数n,表示字符串的长度。 第二行为一个字符串s。 输出格式: 输出一个整数,表示该字符串的最长重复子串长度。 样例输入: 6 ababab 样例输出: 3 算法1: (后缀数组) $O(nlog^2n)$ 我们可以将字符串的所有后缀排序,然后求相邻两个后缀的最长公共前缀,最后取所有公共前缀中的最大值即可。 具体来说,我们可以使用后缀数组来对字符串的所有后缀进行排序,然后使用倍增算法求出相邻两个后缀的最长公共前缀。 时间复杂度: - 后缀数组的构建时间复杂度为O(nlogn)。 - 最长公共前缀的计算时间复杂度为O(nlogn)。 因此,总时间复杂度为O(nlog^2n)。 C++ 代码 算法2: (哈希) $O(nlogn)$ 我们可以将字符串s拆分成多个子串,然后对每个子串进行哈希,最后使用二分查找的方式找到最长的重复子串。 具体来说,我们可以将字符串s拆分成多个子串,然后对每个子串进行哈希。哈希算法可以使用Rabin-Karp算法,时间复杂度为O(n)。 找到哈希值相同的两个子串后,我们可以使用二分查找来判断这两个子串的最长公共前缀的长度。二分查找的时间复杂度为O(logn)。 时间复杂度: - 哈希的时间复杂度为O(n)。 - 二分查找的时间复杂度为O(logn)。 因此,总时间复杂度为O(nlogn)。 C++ 代码 算法3: (Manacher算法) $O(n)$ Manacher算法是一种可以在线性时间内找到一个字符串的所有回文子串的算法。 该算法的核心思想是利用回文子串的对称性,来避免重复计算。具体来说,我们可以通过维护最右边的回文子串的右端点来避免重复计算。 时间复杂度: 该算法的时间复杂度为O(n)。 C++ 代码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值