FBI树

题目描述

我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串。FBI树是一种二叉树,它的结点类型也包括F结点,B结点和I结点三种。由一个长度为2N的“01”串S可以构造出一棵FBI树T,递归的构造方法如下:

  1. T的根结点为R,其类型与串S的类型相同;
  2. 若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1和S2;由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2。
    现在给定一个长度为2N的“01”串,请用上述构造方法构造出一棵FBI树,并输出它的后序遍历[2]序列。

具体样例的树结构如下:
在这里插入图片描述

输入输出格式

输入的第一行是一个整数N(0 ≤ N ≤ 10),第二行是一个长度为2^N的“01”串。

输出包括一行,这一行只包含一个字符串,即FBI树的后序遍历序列。

样例输入

3
10001011

样例输出

IBFBBBFIBFIIIFF

时间限制

1s
注释 Hint
对于40%的数据,N≤ 2;
对于全部的数据,N≤10。
[1] 二叉树:二叉树是结点的有限集合,这个集合或为空集,或由一个根结点和两棵不相交的二叉树组成。这两棵不相交的二叉树分别称为这个根结点的左子树和右子树。
[2] 后序遍历:后序遍历是深度优先遍历二叉树的一种方法,它的递归定义是:先后序遍历左子树,再后序遍历右子树,最后访问根。

本来在洛谷上看到这道题的时候是挺懵的,毕竟我图这边的知识非常薄弱。
样例都不知道怎么来的,还又去确定了一下后序遍历是左右根。
然后发现校OJ上有这道题样例的构造树
在这里插入图片描述
太开心了,一下就明白了。
然后发现和加分二叉树有点像。
题目保证串长是2n,所以这个结构就和线段树是一样的。
我们用root[l][r]表示l-r的根,每次搜出左右子节点的根,如果左等右,根就等于左(右)如果不同就是’F’。
如果找到叶节点我们就根据读入的串来判断’I’和’B’
然后输出的时候根据后序遍历,先输出左右子树,再输出根。

#include<bits/stdc++.h>

#define ll long long
#define MAXN 5000100
#define N 1001
#define INF 0x3f3f3f3f
#define gtc() getchar()

using namespace std;

template <class T>
inline void read(T &s){
	s = 0; T w = 1, ch = gtc();
	while(!isdigit(ch)){if(ch == '-') w = -1; ch = gtc();}
	while(isdigit(ch)){s = s * 10 + ch - '0'; ch = gtc();}
	s *= w;
}

template <class T>
inline void write(T x){
    if(x < 0) putchar('-'), x = -x;
	if(x > 9) write(x/10);
    putchar(x % 10 + '0');
}

int n;
int m = 1;
char a[MAXN];
char root[1500][1500];

void dfs(int l, int r){
	if(l == r){
		root[l][r] = a[l] == '1' ? 'I' : 'B'; return ;
	}
	int mid = (l + r) >> 1;
	dfs(l, mid), dfs(mid + 1, r);
	root[l][r] = root[l][mid] == root[mid+1][r] ? root[l][mid] : 'F'; 
}

void out(int l, int r){
	if(l == r){
		cout << root[l][r]; return ;
	}
	int mid = (l + r) >> 1;
	out(l, mid), out(mid+1, r);
	cout << root[l][r];
}

int main()
{
	read(n);
	for(int i = 1; i <= n; ++i) m *= 2;
	scanf("%s", a+1);
	dfs(1, m);
	out(1, m);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIGBIGPPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值