1. 程式人生 > >HihoCoder1049 後序遍歷 分治水題

HihoCoder1049 後序遍歷 分治水題

== 提示 先來 nss sample 大小 使用 文件 由於

水題,是為了給難題(樹形DP)做鋪墊

描述

在參與過了美食節之後,小Hi和小Ho在別的地方又玩耍了一陣子,在這個過程中,小Ho得到了一個非常有意思的玩具——一棵由小球和木棍連接起來的二叉樹!

小Ho對這棵二叉樹愛不釋手,於是給它的每一個節點都標記了一個標號——一個屬於A..Z的大寫字母,並且沒有任意兩個節點的標號是一樣的。小Hi也瞅準了這個機會,重新鞏固了一下小Ho關於二叉樹遍歷的基礎知識~就這樣,日子安穩的過了兩天。

這天,小Ho正好在求解這棵二叉樹的前序、中序和後序遍歷的結果,但是卻在求出前序遍歷和中序遍歷之後不小心把二叉樹摔到了地上,小球和木棍等零件散落了一地!

小Ho損失了心愛的玩具,正要嚎啕大哭起來,所幸被小Hi發現了,勸說道:“別著急,這不是零件都還在麽?拼起來不就是了?”

“可是我忘記了二叉樹長什麽樣子了!”小Ho沮喪道。

“這個簡單,你不是剛剛求出了這棵二叉樹的前序和中序遍歷的結果麽,利用這兩個信息就可以還原出整棵二叉樹來哦!”

“這樣麽?!!”小Ho止住了淚水,問道:“那要怎麽做呢?”

沒錯!小Ho在這一周遇到的問題便是:給出一棵二叉樹的前序和中序遍歷的結果,還原這棵二叉樹並輸出其後序遍歷的結果。

“這可就要從頭說起了,我們先找一棵二叉樹作為例子吧!”小Hi在紙上畫了畫,遞給了小Ho。

技術分享

“不妨假設你的二叉樹長成這個樣子~”小Hi道。

“可是我的二叉樹並不是長成這個樣子啊!雖然我讀書少,但是你不要騙我好不好!”小Ho一臉氣憤道。

“我都說了是假設!是為了能讓你明白如何通用的去解決這樣的問題!”小Hi無奈道。

“好吧……你接著說。”小Ho算是認可了這個說法。

“那麽對於這棵二叉樹,你先來計算一下它的前序遍歷和中序遍歷的結果吧!”小Hi也是毫不含糊就開始下發任務。

“唔……前序遍歷是ABDEGHCFIJ,中序遍歷……我想想啊……是DBGEHACIJF!”小Ho並沒有花費多長時間就給出了答案。

“你還記得前序遍歷的遞歸定義麽?”小Hi點了點頭又繼續問道。

“是‘根節點’+‘左子樹的前序遍歷’+‘右子樹的前序遍歷’!”小Ho毫不猶豫的答道:“而在這裏體現出來就是‘A‘+‘BDEGH’+‘CFIJ’”。

“那中序遍歷呢?”小Hi繼續問道。

“是‘左子樹的中序遍歷’+‘根節點’+‘右子樹的中序遍歷’!在這裏也就是‘DBGEH’+‘A’+‘CIJF’。”小Ho這次花的時間更少了。

“還記得動態規劃時候我們一般處理的方法麽?我們這裏也可以這樣做哦,如果我們定義post_order(str1, str2)為一棵前序遍歷的結果為str1,中序遍歷的結果為str2的二叉樹的後序遍歷的結果的話,我們有沒有辦法把它化解成為子問題呢?”小Hi道。

“讓我想想……”小Ho拿出紙筆開始演算起來:“如果我要求解post-order(str1, str2)的話,首先不難發現,根據‘前序遍歷’str1=‘根節點’+‘左子樹的前序遍歷’+‘右子樹的前序遍歷’,我可以知道這棵二叉樹的根節點root便是str1的第一個字符!”小Ho道。

而我在知道了‘根節點’root之後,我便可以利用‘中序遍歷’str2=‘左子樹的中序遍歷’+‘根節點’+‘右子樹的中序遍歷’,求解出‘左子樹的中序遍歷’str2L和‘右子樹的中序遍歷’str2R!

接下來,由於一棵子樹的前序遍歷和中序遍歷的長度相同,那麽仍然是根據‘前序遍歷’str1=‘根節點’+‘左子樹的前序遍歷’+‘右子樹的前序遍歷’,我可以知道從str1的第2個字符開始的str2L.length()個字符便是‘左子樹的前序遍歷’str1L,而這之後的部分便是‘右子樹的前序遍歷’str1R!”小Ho說到這裏,頓了頓,希望從小Hi處得到些反饋。

“沒錯!那你準備如何求解post_order(str1, str2)呢?”小Hi肯定道。

“這只要根據之前求出的結果,和‘後序遍歷’=‘左子樹的後序遍歷’+‘右子樹的後序遍歷’+‘根節點’,便可以知道——post_order(str1, str2)=post_order(str1l, str2l)+post_order(str1r, str2r)+root這樣一個式子來!而這個問題的規模——也就是二叉樹的大小,是一直在縮小的,所以是能夠這樣不斷的劃分做下去的!也就是說我之後可以將當前根節點的左子樹又拆分成為兩個問題來解決,一直到當前節點是葉子節點了為止!然後慢慢的將這些答案拼成上層的問題的答案,而這個過程只需要使用遞歸完成就可以了!”

“聽起來很容易的樣子呢!那你要不要趕緊去實現了算法,算出你的寶貝二叉樹長什麽樣呢?”小Hi滿意的點了點頭,隨即笑著問道。

“那是自然!”

輸入

每個測試點(輸入文件)有且僅有一組測試數據。

每組測試數據的第一行為一個由大寫英文字母組成的字符串,表示該二叉樹的前序遍歷的結果。

每組測試數據的第二行為一個由大寫英文字母組成的字符串,表示該二叉樹的中序遍歷的結果。

對於100%的數據,滿足二叉樹的節點數小於等於26。

輸出

對於每組測試數據,輸出一個由大寫英文字母組成的字符串,表示還原出的二叉樹的後序遍歷的結果。

Sample Input

AB
BA
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<memory>
#include<cstring>
using namespace std;
char p[30],m[30];
int vis[30],Len;
void _find(int L,int R)
{
    int i,j,pos=0;
    for(i=1;i<=Len&&!pos;i++) 
     for(j=L;j<=R&&!pos;j++)
      if(p[i]==m[j]) {
            pos=j;
            break;
     }
      
    if(L<pos) _find(L,pos-1);
    if(R>pos) _find(pos+1,R);
    cout<<m[pos];    
    
}
int main()
{
    int i,j;
    scanf("%s",p+1);
    scanf("%s",m+1);
    Len=strlen(p+1);
    _find(1,Len);
    return 0;
}

HihoCoder1049 後序遍歷 分治水題