FBI树
题目描述
我们可以把由"(0)"和"(1)"组成的字符串分为三类:全"(0)"串称为(B)串,全"(1)"串称为I串,既含"(0)"又含"(1)"的串则称为F串。
(FBI)树是一种二叉树,它的结点类型也包括(F)结点,(B)结点和I结点三种。由一个长度为(2^N)的"(01)"串S可以构造出一棵(FBI)树(T),递归的构造方法如下:
- (T)的根结点为(R),其类型与串(S)的类型相同;
- 若串(S)的长度大于(1),将串(S)从中间分开,分为等长的左右子串(S_1)和(S_2);由左子串(S_1)构造R的左子树(T_1),由右子串(S_2)构造(R)的右子树(T_2)。
现在给定一个长度为(2^N)的"(01)"串,请用上述构造方法构造出一棵(FBI)树,并输出它的后序遍历序列。
输入输出格式
输入格式
第一行是一个整数(N(0 le N le 10)),
第二行是一个长度为(2^N)的"(01)"串。
输出格式
一个字符串,即(FBI)树的后序遍历序列。
输入输出样例
输入样例 #1
3
10001011
输出样例 #1
IBFBBBFIBFIIIFF
说明
对于40%的数据,(N le 2);
对于全部的数据,(N le 10)。
noip2004普及组第3题
分析
非常经典的一道二叉树题。根据题意建树,会发现这就是先序遍历。而题目的输出是后序遍历,那么我们就可以考虑,递归先序遍历建树,回溯的过程输出,因为先序遍历回溯就是后序遍历。
这就是大体的框架了。还有一些细节问题,比如字符串读入,和判断FBI
。具体见code
。
代码
/*
* @Author: crab-in-the-northeast
* @Date: 2020-03-08 21:40:08
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2020-03-08 23:22:06
*/
#include <iostream>
#include <cstdio>
std :: string s;
void FBI(int l, int r) {
int mid = (l + r) >> 1;
if(l < r) {
FBI(l, mid);//递归建左子树
FBI(mid + 1, r);//递归建右子树
}
for(int i = l + 1; i <= r; i++)
if(s[i] != s[i - 1] && i != 1) {
putchar('F');//如果当前和前面那个不一样,说明这个子串中既有0又有1,直接输出F,回溯。注意i = 1的情况,边界特判。
return ;
}
//到这里说明子串是纯的,也就是要不然全1,要不然全0
if(s[l] == '0') putchar('B');//全0
else putchar('I');//全1
return ;
}
int main() {
int n;
std :: cin >> n;
std :: cin >> s;
s = " " + s;//我喜欢让字符串初始下标是1,于是就这样了。
FBI(1, 1 << n);
return 0;
}
评测结果
AC 100
:R31542447