zoj 1500 Pre-Post-erous!

来源:互联网 发布:车身结构优化 编辑:程序博客网 时间:2024/05/02 06:49

本篇实为转藏,感谢原文:

http://blog.csdn.net/xsbailong/article/details/7220756

为使读者能够更好的理解代码,这里对源代码做一些讲解。

We are all familiar with pre-order, in-order and post-order traversals of binary trees. A common problem in data structure classes is to find the pre-order traversal of a binary tree when given the in-order and post-order traversals. Alternatively, you can find the post-order traversal when given the in-order and pre-order. However, in general you cannot determine the in-order traversal of a tree when given its pre-order and post-order traversals. Consider the four binary trees below:

All of these trees have the same pre-order and post-order traversals. This phenomenon is not restricted to binary trees, but holds for general m-ary trees as well.


Input

Input will consist of multiple problem instances. Each instance will consist of a line of the form

m s1 s2

indicating that the trees are m-ary trees, s1 is the pre-order traversal and s2 is the post-order traversal. All traversal strings will consist of lowercase alphabetic characters. For all input instances, 1 <= m <= 20 and the length of s1 and s2 will be between 1 and 26 inclusive. If the length of s1 is k (which is the same as the length of s2, of course), the first k letters of the alphabet will be used in the strings. An input line of 0 will terminate the input.


Output

For each problem instance, you should output one line containing the number of possible trees which would result in the pre-order and post-order traversals for the instance. All output values will be within the range of a 32-bit signed integer. For each problem instance, you are guaranteed that there is at least one tree with the given pre-order and post-order traversals.


Sample Input

2 abc cba
2 abc bca
10 abc bca
13 abejkcfghid jkebfghicda
0


Sample Output

4
1
45
207352860


题意:一个k叉树,给定其前序和后序遍历,问其中序遍历方式有多少种。

思路:给定前序和中序无法唯一的确定一棵k叉树,但是每一个结点所在的深度

      却是唯一的。本题可用递归进行计算。每次递归获得每层结点分布的可能性。

      举例 :13 abejkcfghid jkebfghicda

     显然a,b容易确定,由后序知 j,k,e必定为 b 的后代。对 j,k,e 递归可获得j,k,e的位置关系。同理其它元素都可以确定自己所在的层数。

     对于每一层,计算组合数C(m,n)可知(即从m个中选n个),这里的 m表示的是m叉树,而n 则表示该层结点数。

/*这部分为我的理解,非原作者所写:做这道题,首先建议对一棵树不局限于二叉树自己做一下前序遍历和后序遍历试一试。用纸写出遍历顺序即可,你可以发现,前序的第一个肯定是根a,第二个是根的一个儿子b,那么,根的第二个儿子c在哪里呢?注意后序遍历,b之前的肯定是b的子孙,这些子孙在前序遍历中一定在c的前面。于是可以由此得出所有a的儿子。假设树a有solve(a)种方法,那么b有solve(b)种放法,c有solve(c)种方法,solve(a)=C(k,son)*solve(b)*solve(c)递归即可*/

//给原作者代码增添了一些注释#include <iostream>  #include <cstdio>  #include <string.h>  using namespace std;  int k;   //组合数 int C( int m,int n )  {      int i,mul=1;      for( i=0;i<n;i++ )          mul*=(m-i);      for( i=n;i>=1;i-- )          mul/=i;      return mul;  }   //pre为第一个数组,post为第二个数组 int solve( int m,char *pre,char *post )  {      int i=1,j=0,re=1,son=0; //i为pre下标,j为post下标                              //re统计结果,son表示子树个数。      while( i<m )      {//pre[i]实际上就是树根的儿子        while( post[j]!=pre[i] )              j++; //找到一个儿子        son++;  //对找到的儿子的子树递归,看有多少种//子树的长度(j-(i-1)+1)//pre+i,出去根节点的起始位置        re*=solve( j+2-i,pre+i,post+i-1 ); //乘法法则//i变为根的下一个孩子//i+子树长度(j-(i-1)+1);        i=j+2;      }      return re*C( k,son );  }    int main()  {      char pre[30],post[30];      while( scanf( "%d",&k ) && k )      {          scanf( "%s%s",pre,post );          printf( "%d\n",solve( strlen(pre),pre,post ) );      }      return 0;  }  



0 0
原创粉丝点击