我们可以把由"\(0\)"和"\(1\)"组成的字符串分为三类:全"\(0\)"串称为\(B\)串,全"\(1\)"串称为I串,既含"\(0\)"又含"\(1\)"的串则称为F串。
\(FBI\)树是一种二叉树,它的结点类型也包括\(F\)结点,\(B\)结点和I结点三种。由一个长度为\(2^N\)的"\(01\)"串S可以构造出一棵\(FBI\)树\(T\),递归的构造方法如下:
现在给定一个长度为\(2^N\)的"\(01\)"串,请用上述构造方法构造出一棵\(FBI\)树,并输出它的后序遍历序列。
第一行是一个整数\(N(0 \le N \le 10)\),
第二行是一个长度为\(2^N\)的"\(01\)"串。
一个字符串,即\(FBI\)树的后序遍历序列。
3
10001011
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
原文:https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p1087.html