lca and rmq ~簡潔もあるよ!~

34
ERATO若手輪読会 2014/11/19 LCA and RMQ 北海道大学大学院 情報科学研究科 博士1年 井上 祐馬 1

Upload: yuma-inoue

Post on 16-Jul-2015

1.052 views

Category:

Science


1 download

TRANSCRIPT

Page 1: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

LCA and RMQ北海道大学大学院 情報科学研究科

博士1年 井上 祐馬

1

Page 2: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

• LCA: Lowest Common Ancestor (最近共通祖先) • 根付き木 T 上の2頂点 u, v に対するクエリ LCA(u,v) • u と v の祖先であって、もっとも深い頂点 x を返す

• RMQ: Range Minimum Query (区間最小値) • 列 A[1:n] 上の区間 [l, r] に対するクエリ RMQ(l,r) • A[l:r] 中での最小値 A[i] を取るような i を返す

• LCA と RMQ には密接な関係がある

LCAとRMQ

2

u

v

x

id 1 2 3 4 5 6A[id] 1 8 2 6 3 5

l r

i

T

Page 3: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

LCAとRMQ• クエリ処理アルゴリズムの計算量表記: <f(n), g(n)> • f(n): 前処理時間, g(n): 1つのクエリの処理時間

3

・LCA と RMQ を <O(n), O(1)> で解く ・(時間があれば)空間 2n + o(n) bit の  簡潔データ構造で <O(n), O(1)> で処理する

今日の目標

Page 4: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

LCAとRMQ• クエリ処理アルゴリズムの計算量表記: <f(n), g(n)> • f(n): 前処理時間, g(n): 1つのクエリの処理時間

4

LCA を <f(n), g(n)> で解くアルゴリズムが存在 → RMQ は <f(n)+O(n), g(n)+O(1)> で解ける

RMQ を <f(n), g(n)> で解くアルゴリズムが存在 → LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける

定理1

定理2

Page 5: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

RMQ to LCA

5

LCA を <f(n), g(n)> で解くアルゴリズムが存在 → RMQは <f(n)+O(n), g(n)+O(1)> で解ける

定理1

• 列Aを Cartesian Tree に変換 • Cartesian Tree • 値の2分ヒープ構造 • 頂点ラベルはインデックス • 子の左右が列の左右と一致 id 1 2 3 4 5 6

A[id] 1 8 2 6 3 5

13

2

5

46

Page 6: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

RMQ to LCA

6

• RMQ(l,r):Cartesian Tree上でLCA(l,r)を解くことで最小値インデックスが求まる

• Cartesian Treeの構築: O(n) • 最小値そのものが知りたいとき:メモリアクセス O(1)

id 1 2 3 4 5 6A[id] 1 8 2 6 3 5

13

2

5

46

LCA を <f(n), g(n)> で解くアルゴリズムが存在 → RMQは <f(n)+O(n), g(n)+O(1)> で解ける

定理1

Page 7: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

LCA to RMQ

• 木 T を Euler Tour で展開 • Euler Tour: • TをDFSで辿る • 頂点の訪問順で列を定義 • 列の長さは必ず2n-1

7

RMQ を <f(n), g(n)> で解くアルゴリズムが存在 → LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける

定理2

4 65

2

1

3

T

id 1 2 3 4 5 6 7 8 9 10 11

A[id] 1 2 1 3 4 3 5 3 6 3 1

Page 8: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

LCA to RMQ

• LCA(u,v): 深さ配列d上でRMQ(l,r)(l, rはu, vのAでの出現位置)

• Euler Tourへの展開: O(n) • LCAの頂点番号取得: メモリアクセス O(1)

8

RMQ を <f(n), g(n)> で解くアルゴリズムが存在 → LCA は <O(f(n))+O(n), O(g(n))+O(1)> で解ける

定理2

4 65

2

1

3

T

id 1 2 3 4 5 6 7 8 9 10 11

A[id] 1 2 1 3 4 3 5 3 6 3 1

d[id] 0 1 0 1 2 1 2 1 2 1 0

Page 9: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

LCAとRMQ

• 定理より、LCA または RMQ のどちらか一方が <O(n), O(1)> で解ければ、もう一方も<O(n), O(1)>

• LCAとRMQには、それぞれ様々なアルゴリズムが提案されている

9

Page 10: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

RMQのアルゴリズム

10

空間 前処理 クエリ

Segment Tree (動的) O(n) O(n) O(log n)

Sparse Table O(n logn) O(n logn) O(1)

Cartesian Tree + LCA O(n) + ? O(n) + ? O(1) + ?

※ここでは各値を表すのに必要な O(logn) は無視

Page 11: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

LCAのアルゴリズム

11

空間 前処理 クエリ

Doubling O(n logn) O(n logn) O(log n)

Heavy Path Decomposition O(n) O(n) O(1)

Euler Tour + RMQ O(n) + ? O(n) + ? O(1) + ?

※ここでは各値を表すのに必要な O(logn) は無視

Page 12: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

<O(n), O(1)>アルゴリズム

• LCAはHeavy Path Decompositionを利用して、直接 <O(n), O(1)> で解くことが可能

• ただし、簡潔化が難しい

• LCAで必要とされるRMQがある特殊な条件を満たすことを利用して、RMQを <O(n), O(1)> で解く

12

Page 13: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

±1RMQ• LCA: Euler Tour の深さ配列でRMQ • 1回の移動で深さはちょうど1だけ変わる • 深さ配列の隣接要素同士は+1 か -1 だけ異なる

• 隣接要素の変化が ±1 である列上での RMQ を ±1RMQ と呼ぶ • ±1RMQ が <O(n), O(1)> で解ければ、LCA も <O(n), O(1)> で解ける

134 65

2

1

3

id 1 2 3 4 5 6 7 8 9 10 11

A[id] 1 2 1 3 4 3 5 3 6 3 1

d[id] 0 1 0 1 2 1 2 1 2 1 0

+1 +1 +1 +1 +1 -1 -1-1-1-1

Page 14: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

<O(n), O(1)> RMQRMQを <O(n), O(1)> で解く流れ 1. RMQ を Cartesian Tree に変換し、LCA に帰着( 時間・空間: O(n) )

2. LCA を Euler Tour で展開し、±1RMQ に帰着( 時間・空間: O(n) )

3. ±1RMQ を以下のテクニックで <O(n), O(1)> で解く • ブロック分割 • Sparse Table • Table Lookup

14

[Bender et. al. '05]

Page 15: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

ブロック分割• 簡潔データ構造の典型テクニック • 長さnの列を長さs = logn/2のブロックに分割 • ブロックの数 B = 2n/logn • 各ブロックの最小値インデックスを O(n) で前計算

• 全体の RMQ クエリは、以下のクエリに分割される • ブロックの区間に対する RMQ クエリ1回 • ブロック内部に対する RMQ クエリ2回

15

id 1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930A[id] 1 2 1 3 4 3 5 3 6 3 1 8 4 9 11 4 1 5 6 3 2 5 2 5 2 1 9 8 4 1

Page 16: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

ブロック分割• 簡潔データ構造の典型テクニック • 長さnの列を長さs = logn/2のブロックに分割 • ブロックの数 B = 2n/logn • 各ブロックの最小値インデックスを O(n) で前計算

• 全体の RMQ クエリは、以下のクエリに分割される • ブロックの区間に対する RMQ = Sparse Table • ブロック内部に対する RMQ = Table Lookup

16

id 1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930A[id] 1 2 1 3 4 3 5 3 6 3 1 8 4 9 11 4 1 5 6 3 2 5 2 5 2 1 9 8 4 1

それぞれ <O(n), O(1)> で 解ければOK

Page 17: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

Sparse Table• i 番目から長さ2kの区間の最小値インデックスをそれぞれ記憶したO(n logn)のテーブルを持つ

• 構築: O(n logn) • S[i][k+1] = argmin( A[S[i][k]], A[S[i+2k][k]] )

• クエリ: O(1) • RMQ(i, j) = argmin( A[S[i][k]], A[S[j-2k+1][k]] ) • k = floor( log(j-i) ) ← O(1)で求められると仮定

17

id 1 2 3 4 5 6 7 8A[id] 1 2 1 3 4 3 5 3

id 1 2 3 4 5 6 7 8A[id] 1 2 1 3 4 3 5 3構築: クエリ:

Page 18: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

Sparse Table• i 番目から長さ2kの区間の最小値インデックスをそれぞれ記憶したO(n logn)のテーブルを持つ

• B個のブロックに対し、<O(B logB), O(1)> のアルゴリズム

• B = 2n/lognより、B logB = 2n/logn・(log2n - loglogn) = O(n)

18

id 1 2 3 4 5 6 7 8A[id] 1 2 1 3 4 3 5 3

id 1 2 3 4 5 6 7 8A[id] 1 2 1 3 4 3 5 3構築: クエリ:

Page 19: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

Table Lookup• 簡潔データ構造の典型テクニック その2 • ±1 で変化している列の最小値インデックスは、値そのものを見なくても変化量だけ見ればわかる

• すべての変化パターンと区間 [l,r]について、最小値インデックスを記録して参照すればよい • 長さ s の列の変化のパターンは2s通り • よって、<O(s22s), O(1)> のアルゴリズム • s = logn/2より、s22s = O(log2n √n) = o(n)

19

Page 20: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

<O(n), O(1)> RMQRMQ を <O(n), O(1)> で解けた!!! 1. RMQ を Cartesian Tree に変換し、LCA に帰着( 時間・空間: O(n) )

2. LCA を Euler Tour で展開し、±1RMQ に帰着( 時間・空間: O(n) )

3. ±1RMQ を以下のテクニックで <O(n), O(1)> で解く • ブロック分割 • Sparse Table • Table Lookup

20

[Bender et. al. '05]

Page 21: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

-----↓ここから簡潔↓-----

21

Page 22: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

簡潔RMQRMQ を <O(n), O(1)> で解けた!!! 1. RMQ を Cartesian Tree に変換し、LCA に帰着( 時間・空間: O(n) )

2. LCA を Euler Tour で展開し、±1RMQ に帰着( 時間・空間: O(n) )

3. ±1RMQ を以下のテクニックで <O(n), O(1)> で解く • ブロック分割 • Sparse Table • Table Lookup

22

BP (Balanced Parentheses) 表現で2n bitに

BP上の rank( - rank) が深さに対応 → Euler Tour なしに ±1RMQ

分割を多段にすることで o(n) bitに

[Sadakane '07]

Page 23: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

簡潔RMQ• 問題点: BP 上でわかるのは pre-order ⇔ RMQ で求めたいインデックスは Cartesian tree 上では in-order • 対応を覚える場合O(n logn) bit を使う → not 簡潔

• Cartesian Tree に dummy node を n 個付加することで解決 → 4n + o(n) bitに

23

[Sadakane '07]

id 1 2 3 4 5 6A[id] 1 8 2 6 3 5

13

2

5

46( ( ( ) ( ( ) ( ) ) )

1 13 22 8

4 65 3

6 5

Page 24: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

簡潔RMQ• 問題点: BP 上でわかるのは pre-order ⇔ RMQ で求めたいインデックスは Cartesian tree 上では in-order • 対応を覚える場合O(n logn) bit を使う → not 簡潔

• Cartesian Tree に dummy node を n 個付加することで解決 → 4n + o(n) bitに

24

[Sadakane '07]

id 1 2 3 4 5 6A[id] 1 8 2 6 3 5

13

2

5

46( ( ( ) ( ( ) ( ) ) )

1 13 22 8

4 65 3

6 5

2nにしたい

Page 25: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

簡潔RMQ• Cartesian Tree + BP の代わりに 2D-Min Heap + DFUDS (Depth-First Unary Degree Sequence)

• 流れ: • 入力列を 2D-Min Heap を表すDFUDSに変換 • O(n)時間、 DFUDSは 2n bit

• DFUDS に必要な索引を付加 • O(n)時間、索引は o(n) bit

• 索引付き DFUDS 上で LCAを解く • 内部で rank, select, findopen, ±1RMQ 等を使用 • O(1) 時間

25

[Fischer '09]

id 0 1 2 3 4 5 6A[id] -∞ 1 8 2 6 3 5

1

32

54

6

2D-Min Heap

0

DFUDS: ( ( ) ( ( ) ) ( ( ) ) ( ) )

Page 26: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

簡潔RMQ• Cartesian Tree + BP の代わりに 2D-Min Heap + DFUDS (Depth-First Unary Degree Sequence)

• 2D-Min Heap: • 自分より左かつ小さいもののうち、最も右にあるものを親にする

26

[Fischer '09]

id 0 1 2 3 4 5 6A[id]-∞ 1 8 2 6 3 5

13

2 54 6

13254

6Cartesian Tree 2D-Min Heap

0

Page 27: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

簡潔RMQ• RMQ(i, j)は、2D-Min Heap 上では、 • LCA(i, j)が i → RMQ(i, j) = i • それ以外 → RMQ(i, j) = LCA(i, j)の子で、jの先祖

27

[Fischer '09]

id 0 1 2 3 4 5 6A[id]-∞ 1 8 2 6 3 5

2D-Min Heap

13254

6

0i j LCA(2,4)

RMQ(2,4)

Page 28: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

簡潔RMQ• Cartesian Tree + BP の代わりに 2D-Min Heap + DFUDS (Depth-First Unary Degree Sequence)

• DFUDS: • 葉は ( ) • w 個の子 T1, ..., Tw の親は w+1 個の ( と 1個の ) の後、子を続ける.ただし、子の表現は先頭の ( を1つ削る

28

[Fischer '09]

( ( ) ( ( ) ) ( ( ) ) ( ) )id 0 1 2 3 4 5 6d 1 2 1 2 3 2 3 4 3 4 3 2 1 0

A[id] -∞ 1 8 2 6 3 5

13254

6

0

Page 29: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

• RMQ(i, j) 1. l ← select)(U, i+1), r ← select)(U, j) 2. w = ±1RMQ(l, r) 3. if rank)(U, findopen(U, w)) = i, then return i 4. else rank)(U, w)

29

簡潔RMQ [Fischer '09]

U: ( ( ) ( ( ) ) ( ( ) ) ( ) )

id 0 1 2 3 4 5 6d 1 2 1 2 3 2 1 2 3 2 1 2 1 0

A[id] -∞ 1 8 2 6 3 5

13254

6

0 i j

l r

±1RMQ(l,r)

findopen

Page 30: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

• RMQ(i, j) 1. l ← select)(U, i+1), r ← select)(U, j) 2. w = ±1RMQ(l, r) 3. if rank)(U, findopen(U, w)) = i, then return i 4. else rank)(U, w)

30

簡潔RMQ [Fischer '09]

U: ( ( ) ( ( ) ) ( ( ) ) ( ) )

id 0 1 2 3 4 5 6d 1 2 1 2 3 2 1 2 3 2 1 2 1 0

A[id] -∞ 1 8 2 6 3 5

13254

6

0 i j

l r

±1RMQ(l,r)

findopen

DFUDS 上の RMQ では、 w は i と j のLCAの子であり、

jの祖先である (ただし LCA が iのとき w=i ) [Jansson et. al. '07]

Page 31: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

• RMQ(i, j) 1. l ← select)(U, i+1), r ← select)(U, j) 2. w = ±1RMQ(l, r) 3. if rank)(U, findopen(U, w)) = i, then return i 4. else rank)(U, w)

31

簡潔RMQ [Fischer '09]

U: ( ( ) ( ( ) ) ( ( ) ) ( ) )

id 0 1 2 3 4 5 6d 1 2 1 2 3 2 1 2 3 2 1 2 1 0

A[id] -∞ 1 8 2 6 3 5

13254

6

0 i j

l r

±1RMQ(l,r)

findopen

親が preorder わかる

Page 32: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

• RMQ(i, j) 1. l ← select)(U, i+1), r ← select)(U, j) 2. w = ±1RMQ(l, r) 3. if rank)(U, findopen(U, w)) = i, then return i 4. else rank)(U, w)

32

簡潔RMQ [Fischer '09]

U: ( ( ) ( ( ) ) ( ( ) ) ( ) )

id 0 1 2 3 4 5 6d 1 2 1 2 3 2 1 2 3 2 1 2 1 0

A[id] -∞ 1 8 2 6 3 5

13254

6

0 i j

l r

±1RMQ(l,r)

findopen自分の preorder わかる

Page 33: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

割愛したところ• 入力列から直接 2n bit のDFUDSへ O(n) で変換 • 簡潔でない方法: スタックを利用したアルゴリズム • 簡潔な方法: スタックを簡潔にする

• ±1RMQ をより簡潔に • o(n) で隠された部分がより succinct に • 具体的には、(loglogn)2 かかっていたところが loglogn に落とせる

33

Page 34: LCA and RMQ ~簡潔もあるよ!~

ERATO若手輪読会 2014/11/19

まとめ• LCA と RMQは適切に変換することで等価な問題として解ける • LCA to RMQ: Euler Tour, BP, DFUDS • RMQ to LCA: Cartesian Tree, 2D-Min Heap

• LCA で要求される RMQ が ±1RMQ であることを利用し、<O(n), O(1)> を実現する

• 木の簡潔表現と LCA, RMQ の簡潔辞書により、2n + o(n) bitで、<O(n), O(1)> を実現する

34