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 cAll 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.
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个的组合数)
代码如下,递归还是比较容易写的~~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }