Codeforces Round #630 (Div. 2) C. K-Complete Word(字符串)

Word ss of length nn is called kk -complete if

  • ss is a palindrome, i.e. si=sn+1isi=sn+1−i for all 1in1≤i≤n ;
  • ss has a period of kk , i.e. si=sk+isi=sk+i for all 1ink1≤i≤n−k .

For example, "abaaba" is a 33 -complete word, while "abccba" is not.

Bob is given a word ss of length nn consisting of only lowercase Latin letters and an integer kk , such that nn is divisible by kk . He wants to convert ss to any kk -complete word.

To do this Bob can choose some ii (1in1≤i≤n ) and replace the letter at position ii with some other lowercase Latin letter.

So now Bob wants to know the minimum number of letters he has to replace to convert ss to any kk -complete word.

Note that Bob can do zero changes if the word ss is already kk -complete.

You are required to answer tt test cases independently.

Input

The first line contains a single integer tt (1t1051≤t≤105 ) — the number of test cases.

The first line of each test case contains two integers nn and kk (1k<n21051≤k<n≤2⋅105 , nn is divisible by kk ).

The second line of each test case contains a word ss of length nn .

It is guaranteed that word ss only contains lowercase Latin letters. And it is guaranteed that the sum of nn over all test cases will not exceed 21052⋅105 .

Output

For each test case, output one integer, representing the minimum number of characters he has to replace to convert ss to any kk -complete word.

Example
Input
Copy
4
6 2
abaaba
6 3
abaaba
36 9
hippopotomonstrosesquippedaliophobia
21 7
wudixiaoxingxingheclp
Output
Copy
2
0
23
16
大意就是对于一个字符串,每一次操作能改变一个字符,问最少操作多少次能让这个字符串变成有长度为k循环节的回文串。
思路很好想,首先由对称性可知,每个子串也必须都是对称的,所以最终就是要把原字符串转化为k个完全相同的回文子串。让求最少操作次数,不妨对这n/k个长度为k的子串进行分析。每个子串的第i个位置和第k-i+1个位置要相同,所以统计每个子串在这些对称位置出现次数最多的字母,把其他字母转换为这些字母。比如样例的n=6 k=2 abaaba,子串为ab aa ba 在1位置a两次b一次,在2w位置a两次b一次,合计a4次b两次(因为在对称位置要相同,所以得合起来考虑)
ans+=n/k*2-num(出现最多的字母的次数)更新即可。
注意:注释掉的部分的写法会T,而且注意t=1e5的情况下不能memset。
#include <bits/stdc++.h>
using namespace std;
int n,k;
char s[200005];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%d%d",&n,&k);
        scanf("%s",s+1);
        int i,j;
//        int cnt[200005][26]={0};
//        int mmax[200005]={0};
//        for(i=1;i<=n;i+=k)
//        {
//            for(j=i;j<=i+k-1;j++)
//            {
//                cnt[j-i+1][s[j]-'a']++;
//                if(k%2!=0&&j-i+1==k/2+1)
//                {
//                    if(cnt[j-i+1][s[j]-'a']>mmax[k/2+1]) mmax[k/2+1]=cnt[k/2+1][s[j]-'a'];
//                }
//                else
//                {
//                    if(cnt[j-i+1][s[j]-'a']+cnt[k-j+i][s[j]-'a']>mmax[min(k-j+i,j-i+1)]) mmax[min(k-j+i,j-i+1)]=cnt[j-i+1][s[j]-'a']+cnt[k-j+i][s[j]-'a'];
//                }
//            }
//        }
//        int ans=0;
//        for(i=1;i<=k/2;i++)
//        {
//        
//            ans+=n/k*2-mmax[i];
//        }
//        if(k%2!=0)
//        {
//            ans+=n/k-mmax[k/2+1];
//        }
//        cout<<ans<<endl;
        int ans=0;
        for(i=1;i<=k/2;i++)
        {
            int a[26]={0};
            for(j=1;j<=n;j+=k)
            {
                a[s[j+i-1]-'a']++;
                a[s[j+k-i]-'a']++;
            }
            int mmax=0;
            for(j=0;j<26;j++)mmax=max(mmax,a[j]);
            ans+=n/k*2-mmax;
        }
        if(k%2!=0)
        {
            int a[26]={0};
            for(j=1;j<=n;j+=k)
            {
                a[s[j+k/2]-'a']++;
            }
            int mmax=0;
            for(j=0;j<26;j++)mmax=max(mmax,a[j]);
            ans+=n/k-mmax;
        }
        cout<<ans<<endl;

    }
    return 0;
}
原文地址:https://www.cnblogs.com/lipoicyclic/p/12615257.html