C. K-Complete Word


C. K-Complete Word


标签

  • 难想的暴力

简明题意

  • 给定n长的字母序列s,再给一个k。(k|n)
  • 如果说s是k复杂的,需要满足:1.s是回文。2.s满足周期性,且每个周期的长度是k。
  • 现在需要你使得这个s是k复杂的,问最少需要改动多少次(每次可以将一个字母改成任意字母)

思路

  • 首先s是回文串且周期是k,那么每一个周期的字串一定也是回文串。(这个结论,直接拿第一个周期和最后一个周期比对一下就能发现每个周期一定是回文)
  • 有了这个结论就很简单了。我们需要让每个周期变成回文串就行了。
  • 那么每个周期变成什么样的回文串呢?我们按照一个周期的每一位进行考虑。每个周期内的第i位和k-i-1位一定是相同的(因为一个周期是回文),那么我们直接看看所有周期的i位和k-i-1位的哪个字母出现的最多,把其他字母都改成出现最多的字母。假设出现最多的次数是cnt次,那么需要改动的就是 2 ∗ n / k − c n t 2*n/k-cnt 2n/kcnt次。
  • 注意特判一下k为奇数时,正中间那一位。是 n / k − c n t n/k-cnt n/kcnt而不是 2 ∗ n / k − c n t 2*n/k-cnt 2n/kcnt

注意事项


总结

  • 回文串s的周期为T,那么每一个周期一定是回文串。
  • 若干个相同的回文串叠加起来,结果仍然是回文串。

AC代码

#pragma GCC optimize(2)
#include
#include
#include
#include 
#include
#include
#include
#include	
#include
#include
#include
using namespace std;

const int maxn = 1000 + 10;

void solve()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n, k;
		string s;
		cin >> n >> k >> s;
	
		int ans = 0;
		for (int i = 0; i < (k & 1 ? k / 2 + 1 : k / 2); i++)
		{
			int cnt[200] = { 0 };
			for (int j = 0; i + j * k < n; j++)
			{
				cnt[s[i + j * k]]++; 
				if (i + j * k != k - i - 1 + j * k) 
					cnt[s[k - i - 1 + j * k]]++;
			}
			sort(cnt, cnt + 200);
			if ((k & 1) && i == k / 2) ans += n / k - cnt[199];
			else ans += 2 * n / k - cnt[199];
		}
		cout << ans << endl;
	}
}
	
int main()
{
	//freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}


你可能感兴趣的:(#,难想的暴力)