题目
时间限制: 1 Sec 内存限制: 64 MB
题目描述
无
输入
第1行:二叉树的前序遍历顺序 第2行:后序遍历顺序
输出
第1行:1个整数,表示所有可能的二叉树的数量
样例输入
ABC
CBA
样例输出
4
分析
令先序遍历为 s1 ,后序遍历为 s2 。
定义状态
f(l1,r1,l2,r2) :满足先序遍历为 s1[l1,...,r1] ,后序遍历为 s2[l2,...r2] 的子树的棵数。
转移
对于 f(l1,r1,l2,r2) 这棵子树的种类数,一定是:左子树的种类数 × 右子树种类数。注意一点:当左右子树有一个为空时,另一个子树可以“移栽”在空的这个子树的位置上,所以种类数要乘2。
所以,要找出 f(l1,r1,l2,r2) 的两个子树。
能确定的是:
f(l1,r1,l2,r2)
的左子树的根一定是
s1[l1+1]
,原因自己想。
所以,在
s2[l2,...r2]
找到
s1[l1+1]
的位置
p
,那么左右子树在后序中的位置就出来了,分别为
由于在先序中,一个子树一定是连续的一个串,所以在根右边的 0→(p−l2) 个全部是左子树,那剩下的就是右子树了。所以左右子树分别为 s1[l1+1,...,l1+(p−l2+1)] 和 s1[l1+(p−l2+1)+1,...,r1] 。
所以: f(l1,l2,r1,r2)=f(l1+(p−l2+1)+1,r1,p+1,r2−1)∗f(l1+1,l1+(p−l2+1),l2,p) 。
边界
当只有两个结点时,显然return 2
。
只有一个结点,return 1
。
当子树为空时,return 2
(处理之前说的“移栽”的情况)。
当找不到
p
时,说明这个子树也为空了,给
代码
#include<cstdio>
#include<cstring>
#define MAXN 26
char s1[MAXN+5],s2[MAXN+5];
int N;
int Find(char t,int l,int r)
{
for(int i=l;i<=r;i++)
if(s2[i]==t)
return i;
return MAXN+2;//找不到p
}
int dfs(int l1,int r1,int l2,int r2)
{
if(r2<l2) return 2;
if(r2-l2+1<=2) return r2-l2+1;//结点数<=2
int p=Find(s1[l1+1],l2,r2);
return dfs(l1+(p-l2+1)+1,r1,p+1,r2-1)*
dfs(l1+1,l1+(p-l2+1),l2,p);
}
int main()
{
scanf("%s%s",s1+1,s2+1);
N=strlen(s1+1);
printf("%d",dfs(1,N,1,N));
}