【洛谷 P8739】[蓝桥杯 2020 国 C] 重复字符串 题解(字符串+贪心算法)

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

题目描述

如果一个字符串 S S S 恰好可以由某个字符串重复 K K K 次得到,我们就称 S S S K K K 次重复字符串。例如 abcabcabc 可以看作是 abc 重复 3 3 3 次得到,所以 abcabcabc 3 3 3 次重复字符串。

同理 aaaaaa 既是 2 2 2 次重复字符串、又是 3 3 3 次重复字符串和 6 6 6 次重复字符串。

现在给定一个字符串 S S S,请你计算最少要修改其中几个字符,可以使 S S S 变为一个 K K K 次字符串?

输入格式

输入第一行包含一个整数 K K K

第二行包含一个只含小写字母的字符串 S S S

输出格式

输出一个整数代表答案。如果 S S S 无法修改成 K K K 次重复字符串,输出 − 1 −1 1

样例 #1

样例输入 #1

2
aabbaa

样例输出 #1

2

提示

其中, 1 ≤ K ≤ 1 0 5 1 \le K \le 10^5 1K105 1 ≤ ∣ S ∣ ≤ 1 0 5 1 \le |S| \le 10^5 1S105。其中 ∣ S ∣ ∣S∣ S 表示 S S S 的 长度。

蓝桥杯 2020 年国赛 C 组 G 题。


思路

贪心策略:在每个子字符串中,选择出现次数最多的字符作为重复字符,其他不同的字符都需要修改。这是因为出现次数最多的字符意味着需要修改的字符最少,从而总的修改次数也最少。

选择局部最优解以达到全局最优解。在每个子字符串中,都独立地采取这种策略,最后得到的总修改次数就是全局最优解。

首先从输入中读取整数 n n n和字符串 s s s。如果字符串长度不能被 n n n整除,那么就无法将其修改为 n n n次重复的字符串。检查字符串的长度是否能被 n n n整除,如果不能,输出 − 1 -1 1并结束程序。

接下来,定义数组 c n t cnt cnt来统计每个字母出现的次数。计算字符串 s s s的长度并将其除以 n n n,得到每个子字符串的长度 s e g L e n segLen segLen。定义一个变量 s u m sum sum来记录需要修改的字符数量。

然后,遍历字符串 s s s中的每一个子字符串。对于每个子字符串,首先将数组 c n t cnt cnt中的所有元素初始化为 0 0 0。然后遍历每个字符,将其转换为数组下标(通过减去字符’a’),并在 c n t cnt cnt中对应的位置加 1 1 1。这样, c n t [ j ] cnt[j] cnt[j]就表示字母 j j j在当前子字符串中出现的次数。

接着,遍历数组 c n t cnt cnt,找出其中的最大值 m m m m m m表示当前子字符串中出现次数最多的字母的出现次数。那么,为了将当前子字符串修改为 n n n次重复的字符串,需要修改的字符数量就是 n − m n-m nm。将这个数量加到 s u m sum sum上。

最后,输出 s u m sum sum,即需要修改的字符总数量。


AC代码

#include <algorithm>
#include <cmath>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;

const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;

int n;
string s;
int cnt[30];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> n >> s;
	int len = s.length();
	if (len % n) {
		// 不能被n整除
		cout << -1 << "\n";
		return 0;
	}
	// 分段长度
	int segLen = len / n;
	ll sum = 0;
	// 偏移量
	for (int i = 0; i < segLen; i++) {
		// 初始化
		for (int j = 0; j < 26; j++) {
			cnt[j] = 0;
		}
		// 检查每段
		for (int j = 0; j * segLen + i < len; j++) {
			int t = j * segLen + i;
			// cout << t << " " << s[t] << endl;
			cnt[s[t] - 'a']++;
		}
		int m = 0;
		for (int j = 0; j < 26; j++) {
			m = max(m, cnt[j]);
		}
		sum += n - m;
		// cout << m << " " << n - m << endl << endl;
	}
	// cout << sum << endl;
	cout << sum << "\n";
	return 0;
}

最近更新

  1. TCP协议是安全的吗?

    2024-03-31 07:48:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-31 07:48:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-31 07:48:06       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-31 07:48:06       20 阅读

热门阅读

  1. 机器学习(零) -- 系列文章目录及链接

    2024-03-31 07:48:06       19 阅读
  2. Kafka入门到实战-第三弹

    2024-03-31 07:48:06       24 阅读
  3. Linux系统中如何安装rz、sz命令

    2024-03-31 07:48:06       19 阅读
  4. 装箱问题

    2024-03-31 07:48:06       19 阅读
  5. 【R语言从0到精通】-2-数据结构

    2024-03-31 07:48:06       19 阅读
  6. 解释TCP和UDP之间的区别

    2024-03-31 07:48:06       18 阅读
  7. Linux-ntp-ptp-gptp

    2024-03-31 07:48:06       15 阅读
  8. C++入门

    C++入门

    2024-03-31 07:48:06      14 阅读