传送门
题意
一个字符串如果长度为1 并且为’a’ 那么就是 a -good 字符串,
当长度大于1时, 需要满足 : 将总区间划分成一半, 其中一半全是a,另一半必须为b-good 字符串 以此类推
分析
这道题的做法比较直观,不断将字符串分段,然后递归下去,主要思想为分治,时间复杂度为标准的nlogn
代码
用dfs,类似于归并排序的思想,统计出上半段符合当前深度的字母,下半段符合当前深度的字母,然后递归下去即可
好像没有合适的剪枝方法,我剪枝三次一直是WA2,后来直接暴力ac了2333
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int N = 131080;
int a[N];
int dfs(int l,int r,int d){
if(r - l == 1){
if((a[l] == d && a[r] == d + 1 )|| (a[l] == d + 1 && a[r] == d)) return 0;
if(a[l] == d || a[l] == d + 1 || a[r] == d || a[r] == d + 1) return 1;
return 2;
}
int m = (r + l - 1) / 2;
int sum1 = 0,sum2 = 0;
for(int i = l;i <= m;i++) if(a[i] == d) sum1++;
for(int i = m + 1;i <= r;i++) if(a[i] == d) sum2++;
int ans1 =(m - l + 1 - sum2) + dfs(l,m,d + 1);
int ans2 =(m - l + 1 - sum1) + dfs(m + 1,r,d + 1);
return min(ans1,ans2);
}
int main(){
int T,n;
cin >> T;
while(T--){
cin >> n;
char str[N];
cin >> (str + 1);
for(int i = 1;i <= n;i++) a[i] = str[i] - 'a' + 1;
if(n == 1){
if(a[1] == 1)
cout << 0 << endl;
else
cout << 1 << endl;
continue;
}
cout << dfs(1,n,1) << endl;;
}
}