D. a-Good String
题目大意:
定义:字符串s 为一个c-好串(c 为一个字符)时,必须满足:
当|s| = 1∣s∣=1 ,s = c
当|s| > 1, s 的左半部分为全为 c,右半部分为一个 (c+1)-好串 或者 s 的右半部分为全为 c,左半部分为一个 (c+1)-好串
其中 ∣s∣ 代表 字符串 s 的长度。
举个例子:当 s=“cdbbaaaa"时,s 是一个 a-好串
现在,给你一个字符串 s ( |s| = 2^k),问最少替换多少个字符,使其为一个 a-好串。
思路:
肥肠巧妙的一道题,显然,每个字符串的中间位置都是我们所判断的一个特殊的地方。那么我们就可以将其一段一段的从中间分开直到只有一个字母,期间判断操作次数累加取最小值即可。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<sstream>
#include<queue>
#define pi 3.1415926535
#define me(a,b,c) memset(a,b,sizeof c)
#define eps 0.00000001
//#define x first
//#define y second
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e6+10;
char s[N];
int ans(int l, int r, char c) {
if (l == r)return s[l] != c;
int mid = ( l + r )>> 1;
int res1 = 0, res2 = 0;
for (int i = l; i <= mid; i++)if (s[i] != c)res1++;
for (int i = mid + 1; i <= r; i++)if (s[i] != c)res2++;
res1 += ans(mid + 1, r, c + 1);
res2 += ans(l, mid, c + 1);
return min(res1, res2);
}
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
cin >> s + 1;
int h = ans(1, n, 'a');
cout << h << endl;
}
}
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
// Buddha blesses the code with no bugs