T236450 美国血统
农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛 们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而 不是用图形的方法。
你的任务是在被给予奶牛家谱的“树中序遍历”和“树前序遍历”的符号后,创建奶牛家谱的“树的 后序遍历”的符号。每一头奶牛的姓名被译为一个唯一的字母。(你可能已经知道你可以在知道树的两 种遍历以后可以经常地重建这棵树。)显然,这里的树不会有多于 26 个的顶点。 这是在样例输入和 样例输出中的树的图形表达方式:

树的中序遍历是按照左子树,根,右子树的顺序访问节点。
树的前序遍历是按照根,左子树,右子树的顺序访问节点。
树的后序遍历是按照左子树,右子树,根的顺序访问节点。
输入格式
第一行: 树的中序遍历
第二行: 同样的树的前序遍历
输出格式
单独的一行表示该树的后序遍历。
输入输出样例
输入 #1
ABEDFCHG CBADEFGH
输出 #1
AEFDBHGC
思路:因为题目告诉了我们两种遍历的结果,所以从两种递归入手,用l,r,l1,r1来表示两种遍历方式所递归到的左子树或右子树。
我们先寻找到所在子树的根节点,再通过根节点来递归对应的左右子树,再找出其左右子树的根节点,再递归对应的左右子树,重复如此。
但是这道题并非让我们求出树原来的样子,是求出后序遍历,所以我们先需要遍历左子树,再遍历右子树,然后加上根节点。
三种遍历的性质:
先序遍历:
①先序遍历第一个节点是整棵树G的根节点,第二个节点是他的左儿子
②对于先序遍历中的任意一个编号为m的节点,如果已知以这个节点为根节点的左子树结点个数为l,右子树的结点个数为r,那么左子树在先序中的[m+1,m+l],右子树在先序中的[m+l +1,m+l +r]
中序遍历:
对于中序遍历中的任意一个编号为m的节点,如果已知以这个节点为根节点的左子树结点个数为l,右子树的结点个数为r,那么左子树在中序中的[m-l,m-1],右子树在中序中的[m+1,m+r]
后序遍历:
对于后序遍历中的任意一个编号为m的节点,如果已知以这个节点为根节点的左子树结点个数为l,右子树的结点个数为r,那么左子树在后序中的[m-r-l,m-r-1],右子树在后序中的[m-r,m-1]
#include<bits/stdc++.h> using namespace std; char tr[100000]={}; int a[200]={}; int n=0; string s1,s2; void aaa(int l,int r,int l1,int r1){ if (l==r) {tr[++n]=s1[l];return;} for (int i=l;i<=r;i++) if (s1[i]==s2[l1]){ aaa(l,i-1,l1+1,l1+i-l); aaa(i+1,r,l1+i-l+1,r1); tr[++n]=s1[i]; break; } } int main(){ cin>>s1>>s2; for (int i=s1.size();i>=1;i--) s1[i]=s1[i-1],s2[i]=s2[i-1]; aaa(1,s1.size(),1,s2.size()); for (int i=1;i<=n;i++) cout<<tr[i]; return 0; }

浙公网安备 33010602011771号