首页 > 试题广场 >

牛牛喜欢字符串

[编程题]牛牛喜欢字符串
  • 热度指数:1028 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
牛牛现在有一个长度n的字符串(仅包含小写字母),他现在把这个字符串,每隔k个就分出来一个子串,比如[1,k]为第一个子串,[k+1,2k]为第二个、[2k+1,3k]为第三个.....(保证n%k=0) 
牛牛想要把这些子串都变成一样的。他可以选择任意一个子串的任意一个字符进行更改,但是他太懒了,他想让你帮他算算最少要进行多少次操作。

输入描述:
第一行输入n(1≤n≤106)和k(1≤k≤n  数据保证n%k=0),第二行输入该字符串。


输出描述:
输出需要的最少操作次数
示例1

输入

6 2
abaaba

输出

2

说明

改为aaaaaa
示例2

输入

6 3
abbabb

输出

0

这道题其实超简单的说~ (*≧▽≦)

我们只需要把字符串s分成k个子串,每个子串的成员是那些间隔相等的位置上的字母喵~ 
然后对每个子串的相同位置,我们数一数哪种小字母出现得最多,就让其他所有小字母都变成这个最多的小字母
这样需要改动的次数就最少啦!最后把每个子串要改的次数加起来,就是总的改动次数了喵~ 
是不是像变魔法一样简单呢?(ฅ´ω`ฅ)

以下是原代码喵~
#include <bits/stdc++.h>
using namespace std;
using ll=long long;

int main() {
    cin.tie(0)->sync_with_stdio(0);

    string s;
    ll n,k;cin >> n >> k >> s;
    ll ans=0;//结果
    //设s分成n/k个分数组;每个分数组的同一个下标相差为k
    for(int i=0;i<k;i++)//单个分数组的每个下标
    {
        vector<int> cnt(26);//统计每个字母的个数
        for(int j=i;j<n;j+=k)
        {
            int c=s[j]-'a';
            cnt[c]++;
        }

        ll maxn=0;
        for (int k : cnt) 
        {
            if (k > maxn) maxn = i;//得到最多的字母数量
        }
        ans+=n/k-maxn;//让其他的字母改成该字母
    }
    cout << ans;
}
/*
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣤⡀⣀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⡀⢀⣴⣾⣷⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣷⣾⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⠿⠛⠛⠉⠉⠉⠉⠉⠉⠛⠻⠿⣿⣿⣿⣿⣿⣶⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⡿⠿⠛⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠿⣿⣿⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣀⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⣰⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣠⣾⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣶⣄⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣻⣿⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢹⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⠁⠈⢢⡀⠀⠀⠀⢸⡇⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⡟⠒⢦⡀⠀⠀⠀
⠀⠀⣠⣤⣤⣼⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡇⠀⠀⠀⠉⢢⣄⠀⠀⢿⠊⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣷⡄⠀⢷⠀⠀⠀
⠀⢰⠇⠀⣰⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⡌⣹⠗⠦⣬⣇⠀⠉⢢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡀⢸⡄⠀⠀
⠀⡟⠀⣼⣯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣆⢹⡀⠀⠀⠀⠉⠁⠀⠀⢀⣀⡁⠀⠀⠉⠳⢴⡆⠀⠀⠀⠀⠀⠀⢹⣧⠈⡇⠀⠀
⠀⡇⠀⠀⢻⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣾⠻⠉⠛⠂⠀⠀⠀⠀⠀⠀⠻⠿⣿⣿⣿⣶⣦⡀⠛⣇⠀⠀⠀⠀⠀⣈⣿⠀⡇⠀⠀
⢸⡇⠀⠀⢠⣿⣷⣦⣀⡸⣷⣦⣶⡂⠉⠉⠉⢁⣤⣶⡶⠀⠀⠀⣀⣀⡴⠀⠀⠀⠀⠀⠀⠈⠉⠉⠁⠀⡟⢀⣴⣟⣰⣾⣿⣏⣠⠇⠀⠀
⠈⡇⠀⠀⢸⣿⠁⠉⣿⠛⠛⠃⡇⠀⠀⢠⣶⣿⡿⠛⠁⠀⠀⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⢿⠟⠿⢿⡏⠀⠘⣿⡀⠀⠀⠀
⠀⢷⣀⣀⣿⠇⠀⠀⢿⡇⠀⢀⢱⡀⠀⠛⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠀⠀⢸⠇⠀⠀⢹⣿⣄⠀⠀
⠀⠀⣉⣿⡏⠀⠀⠀⠀⠀⠀⢸⣇⣳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⣿⠃⠀⠀⠀⠀⠀⠀⣿⠈⢧⠀
⠀⠘⣿⣿⠁⠀⠀⠀⠀⠀⠀⠘⣿⡛⣶⠀⠀⣠⠔⠒⠛⠒⠦⡀⠀⠀⠀⠀⣠⡤⠶⠤⢤⣀⠀⠀⠀⢀⣏⡄⠀⠀⠀⠀⠀⡀⣿⡆⠈⣧
⣠⡾⠛⣿⣿⣧⠀⠀⠀⠀⢸⣿⠾⢿⡿⠀⣰⠃⠀⠀⠀⠀⠀⢹⡄⠀⠀⡼⠁⠀⠀⠀⠀⠈⠙⣦⠀⢸⣿⡇⣾⣣⡀⠀⢰⣿⣿⣿⣤⠾
⡟⠀⠀⠻⣿⡟⢷⡄⣤⡀⠈⣿⡀⣸⠇⠀⠏⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⡇⢀⡀⠀⠀⠀⠀⢀⡟⠀⠀⠋⣿⣿⣿⡇⣠⣿⠿⠛⢷⡀⠀
⠀⠀⠀⠀⣿⣇⣨⣿⣿⣿⣦⣽⣷⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠃⠀⠙⠢⠤⠤⠴⢾⠀⠀⠀⠀⢸⣷⣿⣿⠟⠁⠀⠀⠈⣧⠀
⠀⠀⠀⠀⠈⠉⠉⠁⠈⠉⠈⢉⣿⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀⠀⣿⠀
*/


发表于 2026-01-09 00:54:11 回复(1)
对于每一个字串最后要让所有的对应位置相同就是下标对k取模相同的位置的字符都要相同,然后统计一下每一个对应位置出现最多的那个,更改其他的就行了
void solve(){
    int n,k;
    cin>>n>>k;
    string s;cin>>s;
    s='0'+s;
    map<int,map<char,int>> f;
    for(int i=1;i<=n;i++){
        f[i%k][s[i]]++;
    }
    int ans=0;
    for(int i=0;i<k;i++){
        int mx=0;
        for(auto [c,cnt]:f[i]){
            mx=max(mx,cnt);
        }
        ans+=(n/k)-mx;
    }
    cout<<ans;
}  


发表于 2026-01-09 15:21:42 回复(0)
又是 Python 过不去的一题。给多点时间啦!
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <string>

// 等价于 Python 中的 MaxCounter 类
class MaxCounter {
public:
    int mx;                      // 对应 Python 中的 self.mx
    std::unordered_map<char, int> cntr;  // 对应 Python 中的 defaultdict(int)

    // 构造函数,等价于 __init__ 方法
    MaxCounter() : mx(0) {}

    // 等价于 add 方法
    void add(char x) {
        cntr[x]++;  // unordered_map 访问不存在的键会默认初始化值为 0,然后自增
        mx = std::max(mx, cntr[x]);
    }
};

int main() {
    int n, k;
    // 读取 n 和 k,等价于 Python 的 map(int, input().split())
    std::cin >> n >> k;
    
    // 读取字符串(注意忽略换行符)
    std::string s;
    std::cin >> s;
    
    // 等价于 [MaxCounter() for _ in range(k)]
    std::vector<MaxCounter> mcs(k);
    
    // 遍历字符串,按模 k 分配到不同的 MaxCounter 实例
    for (int i = 0; i < s.size(); ++i) {
        char x = s[i];
        mcs[i % k].add(x);
    }
    
    // 计算总和并输出结果
    int sum_mx = 0;
    for (const auto& mc : mcs) {
        sum_mx += mc.mx;
    }
    std::cout << (n - sum_mx) << std::endl;
    
    return 0;
}


发表于 2026-01-09 13:52:58 回复(1)