Palindromic Tree
@__MATH
Palindromic Tree(Eertree)とは
•Mikhail Rubinchik さんが作ったデータ構造
• 昔 codeforces にも参加されていた
• 割と最近に発表された、2015年?
何ができるの?
•文字列に含まれる全てのユニークな回文を求める
• それぞれの出現回数も求められる
•i番目が最後尾となるような、異なる長さの回文を求める
•構築がオンラインで出来る
•空間: O(nσ) (nは文字列の長さ、 σは文字種)
• 入力がランダムな文字列の場合 expected O(√nσ) らしい
•計算: O(n)
何ができるの?
•文字列に含まれる全てのユニークな回文を求める
• それぞれの出現回数も求められる
S = “eertreere” の時
“e” : 5回, ”r” : 3回, ”t” : 1回
“ee” : 2回, “rtr” : 1回, “ere” : 1回
“ertre” : 1回, “eertree” : 1回
何ができるの?
•i番目が最後尾となるような、異なる長さの回文を求める
S = “eertreere” の時、i = 5が最後尾となるような回文は
“ertre”, ”e” の2個
◦ 0-indexed
見た目
• S = “eertreere” の時
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
•見づらい
• 辺を減らして表示
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
Sに含まれている回文が頂点
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
Sに含まれている回文が頂点
長さが-1の特殊な頂点
長さが0の特殊な頂点
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
一つ前の回文の両側に一文字足して
出来る回文に辺を張る
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
一つ前の回文の両側に一文字足して
出来る回文に辺を張る
長さが1の回文は長さが-1の回文から作る
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
Suffix Link
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
頂点の文字列に含まれる
最大の回文接尾辞へsuffix linkを張る
Suffix Link
接尾辞
• 文字列の接尾辞とは、(開始位置を異にし終端位置を元の文字
列と同じくする部分文字列)
• Wikipedia より
• https://ja.wikipedia.org/wiki/接尾辞配列
• S = “eertre” の時
eertre
ertre
rtre
tre
re
e
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
頂点の文字列に含まれる
最大の回文接尾辞へsuffix linkを張る
Suffix Link
長さが1の頂点からは、長さ0の頂点へ
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
頂点の文字列に含まれる
最大の回文接尾辞へsuffix linkを張る
Suffix Link
長さが1の頂点からは、長さ0の頂点へ
長さが0の頂点からは、長さ-1の頂点へ
見た目
(-1)
(0)
r t e
ee
ere
reer
ertre
eertree
rtr
• S = “eertreere” の時
完成
Suffix Link
Palindromic Treeのデータ構造
•木を3つ同時に作っていくデータ構造
• 長さが偶数の頂点と、それらを結ぶ辺で構成される木
• 長さが奇数の頂点と、それらを結ぶ辺で構成される木
• 全ての頂点をsuffix linkで結んだ木 (-1)
(0)
r t e
ee
ere rtr
Suffix Link tree
全ての頂点をsuffix linkで結んだ木
◦ これが便利
◦ 公式の呼び方はなさそう?
(-1)
(0)
r t e
ee erertr
作り方 (-1)
(0)
r e
ee
• S = “eer” まで完成
作り方 (-1)
(0)
r e
ee
• S = “eer” まで完成
“eer” の最長の回文接尾辞
作り方 (-1)
(0)
r e
ee
• S = “eer” まで完成
“eert” の頂点を作る
S += “t”
作り方 (-1)
(0)
r e
ee
• S = “eer” まで完成
“eert” のPalindromic treeを作る
• S += “t”
• “t” + “r” + “t” は”eert”の回
文接尾辞ではない
trt?
作り方 (-1)
(0)
r e
ee
• S = “eer” まで完成
“eert” のPalindromic treeを作る
• S += “t”
• “t” + “r” + “t” は”eert”の回文接
尾辞ではない
• Suffix linkを辿り “(0)”へ移
動
作り方 (-1)
(0)
r e
ee
• S = “eer” まで完成
“eert” のPalindromic treeを作る
• S += “t”
• “t” + “r” + “t” は”eert”の回文接
尾辞ではない
• Suffix linkを辿り “(0)”へ移動
• “t” + “” + “t” は”eert”の回
文接尾辞ではない
tt?
作り方 (-1)
(0)
r e
ee
• S = “eer” まで完成
“eert” のPalindromic treeを作る
• S += “t”
• “t” + “r” + “t” は”eert”の回文接
尾辞ではない
• Suffix linkを辿り “(0)”へ移動
• “t” + “” + “t” は”eert”の回文接
尾辞ではない
• Suffix linkを辿り “(-1)”へ移
動
作り方 (-1)
(0)
r e
ee
• S = “eer” まで完成
“eert” のPalindromic treeを作る
• S += “t”
• “t” + “r” + “t” は”eert”の回文接
尾辞ではない
• Suffix linkを辿り “(0)”へ移動
• “t” + “” + “t” は”eert”の回文接
尾辞ではない
• Suffix linkを辿り “(-1)”へ移動
• “t”は”eert”の回文接尾辞!!
t
作り方 (-1)
(0)
r t e
ee
• S = “eertr” まで完成
rtr
作り方 (-1)
(0)
r t e
ee
• S = “eertr” まで完成
rtr
“eertr” の最長の回文接尾辞
作り方 (-1)
(0)
r t e
ee
• S = “eertr” まで完成
“eertre” のPalindromic tree
を作る
• S += “e”
rtr
作り方 (-1)
(0)
r t e
ee
• S = “eertr” まで完成
“eertre” の頂点を作る
S += “e”
“e” + “rtr” + “e” は “eertre”
の回文接尾辞 rtr
ertre?
作り方 (-1)
(0)
r t e
ee
• S = “eertr” まで完成
“eertre” のPalindromic tree
を作る
• S += “e”
“e” + “rtr” + “e” は “eertre”
の回文接尾辞
rtr
ertre“eertre” の最長の回文接尾辞
作り方 (-1)
(0)
r t e
ee
• Suffix Linkの追加
• 元いた頂点 “rtr”から、suffix linkを
辿って “r”へ移動
rtr
ertre
作り方 (-1)
(0)
r t e
ee
• Suffix Linkの追加
• 元いた頂点 “rtr”から、suffix linkを
辿って “r”へ移動
• “ere” は “ertre”の回文接尾辞
ではない
rtr
ertre
ere
作り方 (-1)
(0)
r t e
ee
• Suffix Linkの追加
• 元いた頂点 “rtr”から、suffix linkを
辿って “r”へ移動
• “ere” は “ertre”の回文接尾辞ではな
い
• “r”から、suffix linkを辿っ
て”(0)”へ 移動
rtr
ertre
作り方 (-1)
(0)
r t e
ee
• Suffix Linkの追加
• 元いた頂点 “rtr”から、suffix linkを
辿って “r”へ移動
• “ere” は “ertre”の回文接尾辞ではな
い
• “r”から、suffix linkを辿って”(0)”へ
移動
• “ee”は”ertre”の回文接尾辞で
はない
rtr
ertre
作り方 (-1)
(0)
r t e
ee
• Suffix Linkの追加
• 元いた頂点 “rtr”から、suffix linkを
辿って “r”へ移動
• “ere” は “ertre”の回文接尾辞ではな
い
• “r”から、suffix linkを辿って”(0)”へ
移動
• “ee”は”ertre”の回文接尾辞ではない
• “(0)”から、suffix linkを辿っ
て”(-1)”へ移動
rtr
ertre
作り方 (-1)
(0)
r t e
ee
• Suffix Linkの追加
• 元いた頂点 “rtr”から、suffix linkを
辿って “r”へ移動
• “ere” は “ertre”の回文接尾辞ではな
い
• “r”から、suffix linkを辿って”(0)”へ
移動
• “ee”は”ertre”の回文接尾辞ではない
• “(0)”から、suffix linkを辿って”(-1)”へ
移動
• “e”は”ertre”の回文接尾辞!!
rtr
ertre
何ができるの?(再掲)
•文字列に含まれる全てのユニークな回文を求める
• それぞれの出現回数も求められる
•i番目が最後尾となるような、異なる長さの回文を求める
何ができるの?
•文字列に含まれる全てのユニークな回文を求める
• 頂点数 - 2 すればよい
(0),(-1)の頂点を除く必要あり (-1)(0)
r t
e
ee
ere
reer
ertre
eertree
rtr
何ができるの?
•文字列に含まれる全てのユニークな回文を求める
• 頂点数 - 2 すればよい
•i番目が最後尾となるような、異なる長さの回文を
求める
何ができるの?
•文字列に含まれる全てのユニークな回文を求める
• 頂点数 - 2 すればよい
•i番目が最後尾となるような、異なる長さの回文を求める
• Suffix link treeの深さと一致する
• S = “eertreere” の時、i = 5が最後尾となるような回文は
“ertre”, ”e” の2個
(-1)(0)eertre
計算量
(-1)
(0)
r t e
ee
• 新しい頂点を追加するのにかかる計算量は?
rtr
計算量
(-1)
(0)
r t e
ee
• 新しい頂点を追加するのにかかる計算量は?
• 追加する文字とすでに追加された文字の比較を、
Suffix linkを辿った回数だけ行う
• 1文字と1文字の比較はO(1)
• そのノードが存在するかの確認
• mapならO(log σ)
rtr ertre
計算量
(-1)
(0)
r t e
ee
• 新しい頂点を追加するのにかかる計算量は?
• 追加する文字とすでに追加された文字の比較を、
Suffix linkを辿った回数だけ行う
• 1文字と1文字の比較はO(1)
• そのノードが存在するかの確認
• mapならO(log σ)
• 新しい頂点にSuffix linkを追加するために、さらにsuffix
linkを辿る
rtr ertre
計算量
(-1)
(0)
r t e
ee
• 新しい頂点を追加するのにかかる計算量は?
• 追加する文字とすでに追加された文字の比較を、
Suffix linkを辿った回数だけ行う
• 1文字と1文字の比較はO(1)
• そのノードが存在するかの確認
• mapならO(log σ)
• 新しい頂点にSuffix linkを追加するために、さらにsuffix
linkを辿る
• 新しい頂点の深さは最大で、
(前の頂点の深さ) - (辿った回数) + 3
rtr ertre
計算量
(-1)
(0)
r t e
ee
• 新しい頂点を追加するのにかかる計算量は?
• 追加する文字とすでに追加された文字の比較を、
Suffix linkを辿った回数だけ行う
• 1文字と1文字の比較はO(1)
• そのノードが存在するかの確認
• mapならO(log σ)
• 新しい頂点にSuffix linkを追加するために、さらにsuffix
linkを辿る
• 新しい頂点の深さは最大で、
(前の頂点の深さ) - (辿った回数) + 3
rtr ertre
N回の操作後、深さは最大でも3N回しか増えない
=> 合計の計算量は O(N) * O(log σ)
Appendix
https://arxiv.org/abs/1506.04862
• EERTREE: An Efficient Data Structure for Processing Palindromes in Strings
• http://adilet.org/blog/25-09-14/
• Palindromic tree を解説したブログ

Palindromic tree

Editor's Notes

  • #3 http://codeforces.com/profile/MikhailRubinchik 無理やり日本語読みすれば、ミハエル ルビンチク? 当時のレートが2279 red相当. Redになってやめた? ICPCにもコーチとしてよく参加している
  • #4 Manacher algorithmとの違い 空間計算量が増える代わりに出来ることが大量に増えた 時間計算量は一緒
  • #5 Manacher algorithmとの違い 空間計算量が増える代わりに出来ることが大量に増えた 時間計算量は一緒
  • #6 Manacher algorithmとの違い 空間計算量が増える代わりに出来ることが大量に増えた 時間計算量は一緒
  • #17 正確には、頂点の文字列に含まれる中で自身より真に小さい最大の接尾辞回文、なのだが、長いので省略
  • #18 正確には、頂点の文字列に含まれる中で自身より真に小さい最大の接尾辞回文、なのだが、長いので省略
  • #19 正確には、頂点の文字列に含まれる中で自身より真に小さい最大の接尾辞回文、なのだが、長いので省略
  • #20 正確には、頂点の文字列に含まれる中で自身より真に小さい最大の接尾辞回文、なのだが、長いので省略
  • #31 Suffix linkの張り方は別の例で解説
  • #43 Manacher algorithmとの違い 空間計算量が増える代わりに出来ることが大量に増えた 時間計算量は一緒
  • #44 Manacher algorithmとの違い 空間計算量が増える代わりに出来ることが大量に増えた 時間計算量は一緒
  • #45 Manacher algorithmとの違い 空間計算量が増える代わりに出来ることが大量に増えた 時間計算量は一緒
  • #46 Manacher algorithmとの違い 空間計算量が増える代わりに出来ることが大量に増えた 時間計算量は一緒