9.3单题集训小结

T3:

 

 是的这道题并不是第一题,但是,这是今天收获较大的一道。关于通过二叉树先序遍历和中序遍历求出树的样子这件事,通过这道题,有了阶梯性的进步,得知了这个方法,对于以后的一系列此类问题,都可以用此方法进行举一反三;

思路:

通过先序遍历对树之中的根和子树的根一一求出进行辅助,再用中序遍历递归,找到一个根,由于是中序遍历,所以这个数的左边所有数都是它的左子树子孙节点,右边则是它右子树子孙节点,依照这个原则,递归下去,找到叶子节点都,递归上去与他的父节点建边,这样就可以递归建树了。

注意:

先序遍历依次排下来有可能出现当前范围内的根都被更新,从而找不到根的情况。这样以下的三行代码便可以较为完善的将其避免:

 vis[b[pos]]=1;

while(vis[a[depth]]==1)depth++;
vis[b[pos]]=1;

#include<cstdio>
#include<string>
#include<cstring>

using namespace std;

struct Node{
	int v,nxt;
}tr[4010];
int Head[4010];
int kok=0;

char a[2010];
char b[2010];
char val[2010];

int len;
int root;
int size[4010];
int ans[1000];
bool vv[4010];
bool vis[4010];

inline void add(int u,int v)
{
	kok++;
	tr[kok].v=v;
	
	tr[kok].nxt=Head[u];
	
	Head[u]=kok;
}

inline void qun(int l,int r,int depth,int fath)//开始递归建树
{
	if(l==r){//当l==r时,表明找到了一个最下面的叶子节点,直接建上并且标记方便输出答案
		add(l,fath);
		add(fath,l);
		vv[l]=1;
		vis[b[l]]=1;
		val[l]=b[l];
		return ;
	}
	while(vis[a[depth]]==1)depth++;
	int pos=0;
	for(int i=l;i<=r;i++){
		if(a[depth]==b[i]){
			pos=i;
			break;
		}
	}
	if(pos==0)return;
	if(depth==1)root=pos;
	qun(l,pos-1,depth+1,pos);
	qun(pos+1,r,depth+1,pos);
	if(fath!=0){	//递归完了就表明此节点的以下的节点都已经建立完毕,就将自己和fath建边
		add(pos,fath);
		add(fath,pos);
		vis[b[pos]]=1;
	}
	val[pos]=b[pos];
}

inline void dfs(int now,int fath)
{
	//printf("%c\n",val[now]);
	size[now]=1;//求答案了
	for(int i=Head[now];i;i=tr[i].nxt){
		int v=tr[i].v;
		if(v==fath)continue;
		dfs(v,now);
		size[now]+=size[v];
	}
	if(vv[now]!=1)size[now]--;//不为子节点要减一
}

int main(void)
{
	scanf("%s",a+1);
	scanf("%s",b+1);
	len=(int)strlen(a+1);
	qun(1,len,1,0);
	dfs(root,0);
	//for(int i=1;i<=len;i++)size[i]=size[i]>1?size[i]-1:size[i];
	for(int i=1;i<=len;i++){
		ans[(int)b[i]]=size[i];
	}
	for(int i=1;i<=len;i++){
		for(int j=1;j<=ans[(int)a[i]];j++){
			printf("%c",a[i]);
		}
		printf("\n");
	}
}
/*
123746895
327198564

abcgdfhie
cbgaihefd

*/

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值