![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/738e58d66e1dc0a2c5ee6d546da8b250.png)
题意:
已知一个字符串,问至少需要改变多少个字符,才能使得该字符串成为'a-Good String',s串。
s串的定义如下。
s的长度为1,由字符c组成(即s1 = c);
s的长度大于1,字符串的前半部分仅由字符c组成(即s1 = s2 = ... = sn/2 = c),
而字符串的后半部分(即字符串sn/2+1 = sn/2+2 = ... = sn)是(c + 1)良好的字符串;
s的长度大于1,字符串的后半部分仅由字符c组成(即s1 = s2 = ... = sn/2 = c),
而字符串的前半部分(即字符串sn/2+1 = sn/2+2 = ... = sn)是(c + 1)良好的字符串;
思路:
题意给我们长度为2^k次方的字符串,那提示的到位了,用分治递归是解的出来的。
我们用分治来解决这个问题:
1.分解:将该字符串分解成n个长度为1的字符c
2.求解:判断当前字符串是否是c字符,如果不是那么则要改变。
3.合并:我们每次求出的区间修改数需要合并,最后求出总共的修改数,
4.良好字符串可在前面和后面,所以需要对前面的区间和后面的区间进行统计,看那边更小。
5.我们需要找出 'a-Good String' 的最小修改数,那么就从a开始递归。
AC代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=131072+5;
char str[maxn];
int go(char c, int l, int r) {
if (l == r - 1){
return str[l] != c ? 1 : 0;
}
int mid = (l+r) >> 1;
int c1 = 0, c2 = 0;
for (int i = l; i < mid; ++i) if (str[i] != c) ++c1;
for (int i = mid; i < r; ++i) if (str[i] != c) ++c2;
return min(c1 + go(c+1, mid, r), c2 + go(c+1, l, mid));
}
void solve() {
int n;
scanf("%d%s", &n, str);
printf("%d\n", go('a', 0, n));
}
int main() {
int t;
scanf("%d", &t);
for (int i = 0; i < t; ++i) solve();
return 0;
}