第十一届蓝桥杯
试题 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 的
长度。
解析
以aabbac,k=3为例,即3个片段分别为aa bb ac,将这3个片段纵向排列比较:
在第一列的字母为aba,那么要让他们一样,只需要将b改为a即可,即aaa,由此可知,只需要找到这一列中哪个字母是最多的,那么剩下的字母都改为该字母是操作最少的。同理,第二列abc,由于a、b、c这三个字母在这一列中出现的次数是一样多的,那么这时就随便改,可以改为aaa或bbb或ccc均可。
上述可知,我们只需要统计每一列中出现次数最多的字母出现的次数即可,记为max,那么用一列的长度k减去max,即为该列需要更改的次数,第一列中的字母个数为3(即k值),a出现次数最多且出现了2次,故而在这一列中需要改变的次数为k-2=3-2=1,即该列需要改变1次。同理第二列为3-1=2,即该列需要改变2次。将这两列的次数相加1+2=3,故而需要改变至少3次。
也可以解释为如下:
程序如下:
#include <iostream>
using namespace std;
int main()
{
int k = 0;
string str;
cin >> k;
cin >> str;
int size = str.size();
if((size%k) != 0) {
cout << -1;
return 0;
}
int sum = 0;
int alph[26];//记录该列中26个小写字母出现的次数
int max = 0;//该列中出现的最大次数
int temp = 0;
for(int i=0; i<26; i++)
alph[i] = 0;
for(int i=0; i<size/k; i++){
for(int j=i; j<size; j+=(size/k)){
temp = (int)(str[j]-'a');
alph[temp]++;
}
for(int m=0; m<26; m++)//找到该列中的最大值
if(alph[m]>max) max = alph[m];
sum += (k - max);//将所有列需要修改的次数全部加起来,k-max为需要修改的次数
max = 0;//清零
for(int n=0; n<26; n++)
alph[n] = 0;//将数组清空
}
cout << sum << endl;
return 0;
}