【NOIP】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 构造RR的右子树T_2 。
现在给定一个长度为2^N 的“01”串,请用上述构造方法构造出一棵FBI树,并输出它的后序遍历序列。
输入格式
第一行是一个整数N(0≤N≤10),
第二行是一个长度为2^N 的“01”串。
输出格式
一个字符串,即FBI树的后序遍历序列。
输入输出样例
输入 #1 复制
3
10001011
输出 #1 复制
IBFBBBFIBFIIIFF
说明/提示
对于40%的数据,N≤2;
对于全部的数据,N≤10。
noip2004普及组第3题
分析
按照题意: 我们先将10001011拆分到左右子树长度都为1。。
10001011
1000 1011
10 00 10 11
1 0 0 0 1 0 1 1
然后,按照树的后序遍历输出(先左儿子 再右儿子 再父节点):这里以图左边为例
数字代表输出顺序, 1 是I,0是B,10是F,0是B,0是B,00是B,1000是F
这样就很明了,先读入字符串,然后一直拆成左右子树,直到左右子树都长度只剩1,然后就输出对应的
字母,返回上次,再输出对应字母, 这样就刚好对应 树的后序遍历输出。。
代码
#include<iostream>
using namespace std;
int n;
string s;
void f(int L,int R){
if(R>L){
f(L,(L+R)/2);
f((L+R)/2 +1,R);
}
int B=1,I=1,F;
for(int i=L;i<=R;i++){
if(s[i] == '0'){
I = 0;
}else if(s[i] == '1'){
B = 0;
}
}
if(B){
cout<<'B';
}else if(I){
cout<<'I';
}else{
cout<<'F';
}
}
int main(){
cin>>n>>s;
int len = s.length() -1;
f(0,len);
return 0;
}