FBI树——递归练习

题目

FBI Tree

Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 47(33 users) Total Accepted: 36(33 users) Rating: Special Judge: No
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


Source
2016级新生程序设计全国邀请赛

总的来说,水题。递归(可以体现递归的真正含义)。已经说了是递归,这个题就是把字符串分成两段,左右两段都进入递归。因为题中的根节点要最后判断。所以左右节点递归的返回值进行比较,再输出根节点的字母。这是一棵树,中规中矩的用二叉可以解决,但代码量不少。个人更认可递归的方法


递归代码:

#include
#include
using namespace std;
char s[1005];
char ans(int l,int r){  
    char x,y;
    int mid=(l+r)/2;
    if(l==r){
        if(s[l]=='0'){
            printf("B");
            return 'B';
        }
        else{
            printf("I");
            return 'I';
        }
    }
    else{
        x=ans(l,mid);
        y=ans(mid+1,r);
        if(x==y){
            if(x=='B'){
            printf("B");
            return 'B';
            }
            else if(x=='I'){
                printf("I");
                return 'I';
            }
            else if(x=='F'){
                printf("F");
                return 'F';
            }
        }
        else{
            printf("F");
            return 'F';
        }
    }
}
int main(){
    int T,n;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        n=1<



/***官方标程***/
/*利用指针建立二叉树,再进行后续遍历。
直接构造一棵二叉树即可,可以用最后一层节点来保存2^N个值,
则他们的父亲结点的字符值就已经由左右儿子的B,I决定了,故不用保存串,只需要记录字符值。
*/#include
#include
#include
#include
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;
}





革命尚未成功!


你可能感兴趣的:(FBI树——递归练习)