Hash | 第十一届蓝桥杯决赛 重复字符串

383 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看。活动详情

试题 F: 重复字符串

时间限制: 1.0s 内存限制: 256.0MB 本题总分:15 分

问题描述

如果一个字符串 S 恰好可以由某个字符串重复 K 次得到,我们就称 S 是 K 次重复字符串。例如 “abcabcabc” 可以看作是 “abc” 重复 3 次得到,所以 “abcabcabc” 是 3 次重复字符串。 同理 “aaaaaa” 既是 2 次重复字符串、又是 3 次重复字符串和 6 次重复字 符串。 现在给定一个字符串 S ,请你计算最少要修改其中几个字符,可以使 S 变 为一个 K 次字符串?

输入格式

输入第一行包含一个整数 K。 第二行包含一个只含小写字母的字符串 S 。

输出格式

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

样例输入

2
aabbaa

样例输出

2

【评测用例规模与约定】
对于所有评测用例,1 ≤ K ≤ 100000, 1 ≤ | S | ≤ 100000。其中 | S | 表示 S 的 长度。

思路分析

这道题考察字符串处理。
首先我们观察字符串,如果一个串不能分成k段,那么必然不能重复k次,直接输出-1
然后把字符串分为等长的k段,(len为字符串长度)每段有len/k个字符,然后每个片段进行纵向比较,只需找到一列中出现次数最多的字母,那么剩下的字母都改为该字母就是操作次数最少的
还有,仍旧是开辟一个哈希数组记录26个小写字母出现的次数
值得一提的是,官方数据最后一个测试点过不了是因为数据有误。

AC代码

#include<iostream>
#include<algorithm> 
using namespace std;
int main()
{
    int k,sum=0;
    string s;
    cin >> k >> s;
    int len = s.length();
    if(len%k)
        cout << -1;
    else
    {
    	for(int i=0; i<len/k; i++)
	{
            int max,small[26]={0};//记录该列中26个小写字母出现的次数,max为该列中出现的最大次数
            for(int j=i; j<len; j+=len/k)	
            	small[s[j]-'a']++;
            max =*max_element(small,small+26);//找到该列中的最大值
            sum += k-max;//将所有片段需要修改的次数全部加起来,k-max为需要修改的次数
    	}
    	cout << sum;
    }
    return 0;
}