农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而不是用图形的方法。 你的任务是在被给予奶牛家谱的“树中序遍历”和“树前序遍历”的符号后,创建奶牛家谱的“树的后序遍历”的符号。每一头奶牛的姓名被译为一个唯一的字母。(你可能已经知道你可以在知道树的两种遍历以后可以经常地重建这棵树。)显然,这里的树不会有多余26个的顶点。这是在样例输入和样例输出中的树的图形表达方式:
C
/ \
/ \
B G
/ \ /
A D H
/ \
E F
树的中序遍历是打印左子树,根和右子树;树的前序遍历是打印根,左子树和右子树;树的后序遍历是打印左子树,右子树和根。
输入给出前序遍历和中序遍历,求出后序遍历。
分析:算法:很明显的一题递归啊!
思路:这道题我们主要是根据二叉树前/中/后遍历来如说(具体怎样遍历题目上已经讲解)。因为告诉我们两种遍历结果,所以我们的递归就可以从这两种递归入手——用l,r,l1,r1来表示两种遍历方式所递归到的区间(左子树或右子树)。我们先寻找到所在子树的根节点,再通过根节点来递归其对应的左右子树,在找出其左右子树对应的根节点,再递归其对应的左右子树,在……
但这道题显然不是让我们求出这可树原来的样子,是求出后序遍历。既然这样,我们就得有一个先后顺序——因为后序遍历是左右根,我们就需要遍历左子树,再遍历右子树,最后加上根节点。只有这样才能求出后序遍历。
那么具体代码如下:
#include<bits/stdc++.h>
using namespace std;
char tr[100001]={};
int a[201]={};
int n=0;
string s1,s2;
void dfs(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]){
dfs(l,i-1,l1+1,l1+i-l);//先累加左子树
dfs(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];
dfs(1,s1.size(),1,s2.size());
for (int i=1;i<=n;i++) cout<<tr[i];
return 0;
}