POJ 1240 Pre-Post-erous!

Pre-Post-erous!
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 1976   Accepted: 1206

Description

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:
    a   a   a   a
    /   /     \   \
   b   b       b   b
  /     \     /     \
 c       c   c       c
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

二叉树遍历的问题,给出一个二叉树的前序遍历和后序遍历,并不一定唯一确定这棵二叉树,题目要求求出一共可能确定多少种二叉树
我的思路大概如下:
  对于给出的前序遍历,它的第一个节点是根节点(或子树的根节点),第二个节点是该树(或子树)的左子树(或左侧第一棵子树)的根节点,在后序遍历中从头搜索这个子树根节点,搜索到该节点后,就可以确定该子树一共包含有多少个节点(因为后序遍历是遍历完子树的所有节点后才到达子树的根节点),再根据这个节点数返回到前序遍历中,寻找到它第二棵子树的根节点,以此类推,将树还原回去(用vector模拟邻接表存储)
  将树还原好以后,再根据树确定一共可能有多少种情况,做法就是扫描每一个节点有多少个儿子,在结果中乘上C(m,儿子数),求出最终结果即可(C(a,b)表示a个元素中取b个的组合数)
代码如下,递归还是比较容易写的~~

 1 #include<iostream>
 2 #include<cstring>
 3 #include<vector>
 4 
 5 using namespace std;
 6 
 7 int m;
 8 char s1[30],s2[30];
 9 vector<char> tree[30];
10 
11 long long c(int a,int b)
12 {
13     long long result=1;
14     for(int i=1;i<=b;i++)
15         result=result*(a+1-i)/i;
16     return result;
17 }
18 
19 void f(char *s1,char *s2,int len)
20 {
21     int i=1,j=0,head=0;
22     long long ans=0,result=0;
23 
24     if(len==1)
25         return ;
26 
27     while(i<len)
28     {
29         for(;j<len;j++)
30             if(s1[i]==s2[j])
31                 break;
32         f(&s1[i],&s2[head],j-head+1);
33         tree[s1[0]-'a'].push_back(s1[i]);
34         i=j+2;
35         head=j+1;
36     }
37 }
38 
39 int main()
40 {
41     while(cin>>m)
42     {
43         if(m==0)
44             break;
45         cin>>s1>>s2;
46         for(int i=0;i<30;i++)
47             tree[i].clear();
48         f(s1,s2,strlen(s1));
49         long long result=1;
50         for(int i=0,t=strlen(s1);i<t;i++)
51             if(!tree[i].empty())
52                 result*=c(m,tree[i].size());    
53         cout<<result<<endl;
54     }
55 
56     return 0;
57 }
[C++]

 

posted @ 2013-05-17 18:42  ~~Snail~~  阅读(386)  评论(0编辑  收藏  举报