【重走普及路】【树】FBI树

题目描述

我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串。
FBI树是一种二叉树,它的结点类型也包括F结点,B结点和I结点三种。由一个长度为2^N的“01”串S可以构造出一棵FBI树T,递归的构造方法如下:
1)      T的根结点为R,其类型与串S的类型相同;
2)      若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1和S2;由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2。
现在给定一个长度为2^N的“01”串,请用上述构造方法构造出一棵FBI树,并输出它的后序遍历序列。

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:
3
10001011
输出样例#1:
IBFBBBFIBFIIIFF

说明

对于40%的数据,N <= 2;
对于全部的数据,N <= 10。

noip2004普及组第3题


事先说明 我的方法很愚蠢 只是为了接触树的一些算法

那么。。。树这种神奇的东西,题目中的树是满二叉树。。。所以可用三个数组表示:

tree[i] 第i个节点的字符('F','B','I')

treel[i] 第i个节点的左子树

treer[i] 第i个节点的右子树

当然要自下而上构建树更好。。。不解释 然后后序遍历一遍即可

——2015.12.29

var n,t,i,t1:longint;
    s:ansistring;
    tree:array[0..3000] of char;
    treel,treer:array[0..2049] of integer;

procedure ok(t:longint); //后序遍历
begin
    if t=0 then exit;
    ok(treel[t]);  //后序遍历  左 右 中
    ok(treer[t]);
    write(tree[t]);
end;

begin
    readln(n);
    readln(s);
    if n=0 then begin //特殊情况特殊考虑~
        if s='1' then writeln('I')
        else writeln('B');
        close(input);
        close(output);
        halt;
    end;
    t:=1;
    for i:=1 to n do t:=t*2;
    for i:=t to 2*t-1 do begin //把树的“叶子”(即底层)构建好
        inc(t1);
        if s[t1]='0' then tree[i]:='B'
        else tree[i]:='I';
    end;
    for i:=t-1 downto 1 do begin  //(自下而上构建)
        treel[i]:=2*i;//不解释
        treer[i]:=2*i+1; //不解释
        if (tree[2*i]='B')and(tree[2*i+1]='B') then tree[i]:='B'
        else if (tree[2*i]='I')and(tree[2*i+1]='I') then tree[i]:='I'
        else tree[i]:='F';  //判断当前节点的字符
    end;
    ok(1);
end.


你可能感兴趣的:(重走普及路)