FBI Tree

Description

FBI Tree的描述如下:

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

(1)   T的根节点为R,其类型与串S的类型相同。

(2)   若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1S2;由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2

现在给出一个长度为2^N01串,请用上述构造方法构造出一棵FBI树,并输出它的后续遍历序列。

Input

第一行为一个正整数T,表示测试数据组数。

每组测试数据第一行为一个整数N0 <= N <= 10),第二行是一个长度为2^N01串。

Output

输出FBI树的后续遍历序列。

Sample Input

2

1

10

3

10001011


Sample Output

IBF

IBFBBBFIBFIIIFF


第一眼看到这个题目还想着建立一棵二叉树啥的,后来发现人家题解和我想的也是一样的,不过我后来用了二分法的思想来上这个题,完美通过

这是我的代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
char s[1030];
void pos(int st,int en){
    if(st==en){
        if(s[st]=='0')
            printf("B");
        else
            printf("I");
        return;
    }
    int flagb=0;
    int flagi=0;
    int i;
    int mid;
    for(i=st;i<=en;i++){
        if(s[i]=='0')
            flagb=1;
        if(s[i]=='1')
            flagi=1;
    }
    mid=st+en;
    mid/=2;
    pos(st,mid);
    pos(mid+1,en);
    if(flagb&&flagi)
        printf("F");
    else if(flagb&&!flagi)
        printf("B");
    else
        printf("I");
}
int main(){
    int i,j,k;
    int kase;
    scanf("%d",&kase);
    int n;
    while(kase--){
        scanf("%d",&n);
        n=pow(2,n);
        getchar();
        for(i=1;i<=n;i++)
            scanf("%c",&s[i]);
        pos(1,n);
        printf("\n");
    }
    return 0;
}


这是人家的题解:

利用指针建立二叉树,再进行后续遍历。

直接构造一棵二叉树即可,可以用最后一层节点来保存2^N个值,则他们的父亲结点的字符值就已经由左右儿子的B,I决定了,故不用保存串,只需要记录字符值。

#include <iostream> 
#include <cstring>
#include <cstdio>
#include <cmath> 
using namespace std; 
char s1[2]="0",s2[2]="1"; 
char s[1200]; 

struct FBI
{ 
    char s; 
    FBI *lchild,*rchild; 
}; 

void showtree(FBI *head)//后序遍历树
{    
    if(head==NULL) 
    return; 
    showtree(head->lchild); 
    showtree(head->rchild); 
    printf("%c",head->s); 
} 

void maketree(FBI *node,char *p,int len)
{ 
    if(len==1)
    { 
        if(strstr(p,s1)&&strstr(p,s2)) 
        node->s='F'; 
        else if(strstr(p,s1)&&!strstr(p,s2)) 
        node->s='B'; 
        else if(!strstr(p,s1)&&strstr(p,s2)) 
        node->s='I'; 
        node->lchild=NULL; 
        node->rchild=NULL; 
        return; 
    } 
    char q[520],*r=new char;  
    FBI *z=new FBI; 
    strncpy(q,p,len/2); 
    r=p; 
    int i=len/2; 
    while(i--) 
    r++;        //将p一分为二 q和r两个字符串 
    if(strstr(q,s1)&&strstr(q,s2))   //判断左儿子的类型 
    z->s='F'; 
    else if(strstr(q,s1)&&!strstr(q,s2)) 
    z->s='B'; 
    else if(!strstr(q,s1)&&strstr(q,s2)) 
    z->s='I'; 
    node->lchild=z; 
    FBI *c=new FBI; 
    if(strstr(r,s1)&&strstr(r,s2))    //判断右儿子的类型 
    c->s='F'; 
    else if(strstr(r,s1)&&!strstr(r,s2)) 
    c->s='B'; 
    else if(!strstr(r,s1)&&strstr(r,s2)) 
    c->s='I'; 
    node->rchild=c; 
    maketree(z,q,len/2);   //递归构建 
    maketree(c,r,len/2); 
} 

int main()
{ 
    int T;
    scanf("%d", &T);
    while(T--)
    { 
        int n;
        scanf("%d", &n);
        scanf("%s",&s); 
        if(strlen(s)==1)
        { 
            if(!strcmp(s,"0")) 
            printf("B\n"); 
            else if(!strcmp(s,"1")) 
            printf("I\n"); 
            continue; 
        } 
        FBI *head=new FBI; 
        char s1[2]="0",s2[2]="1"; 
        if(strstr(s,s1)&&strstr(s,s2)) 
        head->s='F'; 
        else if(strstr(s,s1)&&!strstr(s,s2)) 
        head->s='B'; 
        else if(!strstr(s,s1)&&strstr(s,s2)) 
        head->s='I'; 
        maketree(head,s,(int)pow(2.0,(double)n)); 
        showtree(head); 
        printf("\n"); 
    } 
    return 0; 
}


做题人虐出题人啊


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值