Files
python/TangDou/LuoGuBook/P1087_2.cpp

103 lines
2.7 KiB
C++
Raw Normal View History

2025-08-30 18:35:01 +08:00
#include <bits/stdc++.h>
using namespace std;
//需要开大一点,否则RE,得了90分。
const int N = 1e5 + 10;
/**
以1011为例
1011
10 11
1 0 1 1
F(7)
F(3) I(6)
I(1) B(2) I(4) I(5)
后序:IBFIIIF(遍历顺序已标注)
(编号为二叉树深度)
1.比如1011,很明显是F
2.然后先不输出,先遍历左子树10(F)
3.还是不输出先遍历左子树1(I)
3.发现不能再分(长度为1时停止)输出 I
2.回到10 继续遍历右子树0(B)
3.发现不能再分,输出B
2.回到10, 所有子树遍历完毕,于是输出F
1.回到1011,遍历右子树11(I)
2.先不输出,继续遍历左子树1(I)
3.发现不能再分,输出I
2.回到11, 遍历右子树1(I)
3.发现不能再分,输出I
2.回到11,子树全部遍历完毕,于是输出I
1.回到1011,输出F
*/
//树的结构体+存储数组
struct Node {
int id; //id编号
int left; //左结点
int right; //右结点
char value; //当前结点的value值
} t[N];
int n, m;
string s; //2^n长度的01串
/**
* 功能:获取字符串s的类型
* @param s
* @return
*/
char getStype(string s) {
int zeroCnt = 0, oneCnt = 0;
for (int i = 0; i < s.length(); i++) if (s[i] == '1') oneCnt++; else zeroCnt++;
if (oneCnt == 0)return 'B';
else if (zeroCnt == 0) return 'I';
return 'F';
}
/**
* 功能:构建FBI树
* @param start 开始的位置
* @param end 结束的位置
*/
void build(string s, int pos) {
/**
递归的构造方法如下:
T的根结点为R,其类型与串S的类型相同;
若串S的长度大于1,将串S从中间分开,分为等长的左右子串S_1和S_2
由左子串S_1构造R的左子树T_1,由右子串S_2构造R的右子树T_2
*/
char v = getStype(s);
t[pos].id = pos;
t[pos].value = v;
if (s.length() > 1) {
t[pos].left = 2 * pos;
t[pos].right = 2 * pos + 1;
//左树
build(s.substr(0, s.length() / 2), t[pos].left);
//右树
build(s.substr(s.length() / 2), t[pos].right);
}
}
//利用递归进行后序遍历
void post_order(Node node) {
if (node.id) {
post_order(t[node.left]);
post_order(t[node.right]);
cout << node.value;
}
}
int main() {
//这个n是无用的,因为是上古的考题,都是C时代的,要求使用char数组,没有n说不过去,现在都用string了,不需要n了。
cin >> n >> s;
//利用递归构建FBI树
build(s, 1);
//进行后序遍历
post_order(t[1]);
return 0;
}