一、最近公共祖先(Least Common Ancestors)
對于有根樹T的兩個結(jié)點u、v,最近公共祖先LCA(T,u,v)表示一個結(jié)點x,滿足x是u、v的祖先且x的深度盡可能大。另一種理解方式是把T理解為一個無向無環(huán)圖,而LCA(T,u,v)即u到v的最短路上深度最小的點。
這里給出一個LCA的例子:
例一
對于T=<V,E>
V={1,2,3,4,5}
E={(1,2),(1,3),(3,4),(3,5)}
則有:
LCA(T,5,2)=1
LCA(T,3,4)=3
LCA(T,4,5)=3
二、RMQ問題(Range Minimum Query)
RMQ問題是指:對于長度為n的數(shù)列A,回答若干詢問RMQ(A,i,j)(i,j<=n),返回數(shù)列A中下標(biāo)在[i,j]里的最小值下標(biāo)。這時一個RMQ問題的例子:
例二
對數(shù)列:5,8,1,3,6,4,9,5,7 有:
RMQ(2,4)=3
RMQ(6,9)=6
RMQ問題與LCA問題的關(guān)系緊密,可以相互轉(zhuǎn)換,相應(yīng)的求解算法也有異曲同工之妙。
下面給出LCA問題向RMQ問題的轉(zhuǎn)化方法。
對樹進行深度優(yōu)先遍歷,每當(dāng)“進入”或回溯到某個結(jié)點時,將這個結(jié)點的深度存入數(shù)組E最后一位。同時記錄結(jié)點i在數(shù)組中第一次出現(xiàn)的位置(事實上就是進入結(jié)點i時記錄的位置),記做R[i]。如果結(jié)點E[i]的深度記做D[i],易見,這時求LCA(T,u,v),就等價于求E[RMQ(D,R[u],R[v])],(R[u]<R[v])。例如,對于第一節(jié)的例一,求解步驟如下:
數(shù)列E[i]為:1,2,1,3,4,3,5,3,1
R[i]為:1,2,4,5,7
D[i]為:0,1,0,1,2,1,2,1,0
于是有:
LCA(T,5,2) = E[RMQ(D,R[2],R[5])] = E[RMQ(D,2,7)] = E[3] = 1
LCA(T,3,4) = E[RMQ(D,R[3],R[4])] = E[RMQ(D,4,5)] = E[4] = 3
LCA(T,4,5) = E[RMQ(D,R[4],R[5])] = E[RMQ(D,5,7)] = E[6] = 3
易知,轉(zhuǎn)化后得到的數(shù)列長度為樹的結(jié)點數(shù)的兩倍加一,所以轉(zhuǎn)化后的RMQ問題與LCA問題的規(guī)模同次