二叉树的计数(count-tree)
题目描述
输入
第1行:二叉树的前序遍历顺序
第2行:后序遍历顺序
输出
第1行:1个整数,表示所有可能的二叉树的数量
样例输入1
ABC
CBA
样例输出1
4
样例输入2
ABCEDFGH
ECDBHGFA
样例输出2
8
分析:
首先很容易得出3个性质:
1,若后序输出只有两个结点,那么这棵树的形态有2种可能
2,若只有一个结点,只有一种可能
3,在先序遍历中,A的右边第一个字母一定是A的左儿子(若左树不为空)
4,在后序遍历中,A的左右儿子一定在A的左侧
根据性质3与性质4,可以把一颗二叉树分为左子树和右子树
根据乘法原理,二叉树所有可能的情况 = 左子树可能的情况 * 右子树可能的情况
由此则可以递归,递归边界便是性质1,2
但是还要注意一点,若二叉树的其中一个子树为空,那么因为后序遍历的性质,不为空的子树既可以为左子树,也能为右子树
so,性质5:若递归的当前结点数=0,返回2
例如样例1:先找到B是A的左儿子,再找到后序中B的坐标,把A的左右子树分为 CB--空 =2*2=4
再例如样例2:结合性质3与性质4把A的左右子树分为 ECDB--HGF 。ECDB--> EC--D =2*1 =2; HGF --> HG--空 =2*2=4 ; ECDB * HGF =2*4=8。
代码如下:
#include<cstdio>
#include<cstring>
char a[100],b[100];
int xmy(int x,int y,int q,int w)//x,y为此树在后序遍历中的坐标,q,w为此树在先序遍历中的坐标
{
if(w-q<0) return 2;
if(w-q<2) return w-q+1;
int p=strchr(b,a[q+1])-b;//找左儿子
return xmy(x,p,q+1,q+1+p-x)*xmy(p+1,y-1,q+2+p-x,w);//拆分
}
int main()
{
//freopen("count-tree.in","r",stdin);
//freopen("count-tree.out","w",stdout);
scanf("%s%s",a,b);
int n=strlen(a);
printf("%d",xmy(0,n-1,0,n-1));
}