Description |
FBI Tree的描述如下: 我们可以把由0和1组成的字符串分为3类,全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树,并输出它的后续遍历序列。 |
Input |
第一行为一个正整数T,表示测试数据组数。 每组测试数据第一行为一个整数N(0 <= N <= 10),第二行是一个长度为2^N的01串。 |
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;
}
做题人虐出题人啊