Skip to content →

接尾辞木で解ける問題

接尾辞木(suffix tree)でできること。

  • 文字列Sは部分文字列Tを持つか O(|T|)
    • 接尾辞木でTの文字を順に辿れば良い。
  • 文字列Sに含まれる部分文字列Tの位置を全て報告せよ。出現回数を occ
    として O(|T|+occ)

    • 接尾辞木でTの文字を順に辿れば良い。根を除いて、次数 2 の内部頂点が存在しないことから、葉の数が occ の部分木の頂点数は O(occ) である。従って、根からのパスのラベルがTとなるような頂点の部分木についてDFSして葉を列挙すれば良い。
  • 部分文字列の種類数
    • Trieの根からのパスの個数、すなわち、Trieの頂点数に等しい。
  • S[i:]とS[j:]のLCP O(1)
    • S[i:]とS[j:]に対応する葉のLCA
  • 各iについてΣ[j]|LCP(S[i:], S[j:])|の列挙 O(|S|)
    (ABC213F)

    • (LCAの深さ+1)の和を上手く取れば良い。
  • i=1,..,|S|に対して、i/2を中心とする極大な回文の列挙 O(|S|)
    • S[i+1:]とrev(S)[|S|-i+1:]のLCPと言い換えられる。LCPはLCAでO(1)
  • 2回以上現れる部分文字列のうち、最長であるもの
    • 深さ最大の内部頂点に対応する部分文字列。
  • S, T の最長共通部分文字列 O(|S|+|T|)
    • S, T 両方の終端文字を子孫に持つ深さ最大の内部頂点のパスラベル
  • S[1]+S[2]+..+S[k] の接尾辞木からS[i]の接尾辞木を構築せよ O(|S[i]|)
    • S[i]の接頭辞を辞書順に並べる(接頭辞の葉を左から順に並べる)。隣り合う者同士のLCAでS[i]の接尾辞木の内部頂点が尽くされる。
  • Sの各部分文字列に対して、T[1],T[2],..,T[k] のうち何個が部分文字列として含まれるか数えよ。 O(|S|+Σ|T[i]|)
    • 特定の終端文字に着目する。その終端文字の頂点を DFS – in-order で並べて、隣り合う頂点の LCA を O(1) で計算する。各頂点について、部分木内の LCA に選ばれた頂点の個数は、max(0, (特定の終端文字の個数) – 1) に等しい。従って、和を取ると、(終端文字の個数) – (終端文字の種類数) となる。部分期に含まれる終端文字の個数は簡単に求まるので、終端文字の種類数も求まる。
  • 文字列Sが円環状になっている。好きな位置で切ったときにできる辞書順最小の文字列を求めよ O(|S|)。
    • S+Sの辞書順最小の接尾辞を求めれば良い。
  • 各iについて、T[i:]がS[1],..,S[k]のうち何個を接頭辞として持つか列挙せよ
    • Tの接尾辞木に対して、S[1],S[2],..,S[k]に対応する頂点の部分木にそれぞれ1加える。和が接頭辞の個数に等しい。
  • 各iについて、T[:i]がS[1],..,S[k]のうち何個を接尾辞として持つか列挙せよ
    • reverseして接頭辞に帰着する。
  • 全てのペア(i,j)について、S[i]+S[j]がTに何箇所部分文字列として含まれるかの総和を求めよ。(ECR070E)
    • T[:i]に接尾辞として含まれるS[1],..,S[k]の個数をf(i), T[i+1:]に接頭辞として含まれるS[1],..,S[k]の個数をg(i+1)としてΣf(i)g(i+1)が求まれば良い。
  • Sの接尾辞木をS+Tの接尾辞木に更新せよ。
    • Ukkonenのアルゴリズム
  • 各iについて、S[:i]が部分文字列としてTに何個含まれるか求めよ O(|S|)
    • iの昇順に接尾辞木で探索すれば良い。S[:i+1]の探索にはS[:i]の探索を再利用する。
  • Sの部分文字列の集合の要素のうち、辞書順でk番目のものを求めよ。
    • 二分探索木とほぼ同様
  • Sの部分文字列のうち、辞書順でTより大きい最小の部分文字列を答えよ。O(|S|)
    • 二分探索木とほぼ同様
  • Sの部分文字列のうち、uniqueな回分の個数を答えよ O(|S|)
  • Sの部分文字列のうち、uniqueな回分の辞書順 k 番目のものを答えよ O(|S|)

Published in データ構造

Comments

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA