最長増加部分列(LIS)
最長増加部分列とは
数列 {$ \small A_i$} が与えられたとき、並び順は変えずに {$ \small A_i $} の中からいくつかの要素を選んで作った数列を数列 {$ \small A_i$} の部分列といい、{$ \small A_i $} の部分列のうち、$ \small i<j$ ならば $ \small A_i < A_j$ がすべての $\small i < j$ に対して成り立つものを数列 {$ \small A_i$} の増加部分列という。数列 {$ \small A_i$} の増加部分列のうち長さが最長のものを最長増加部分列という。
最長増加部分列(LIS)の長さを求めるアルゴリズム
同じ長さの増加部分列ならば、最終要素が小さいほうがその後有利になる。長さに対する最小の最終要素をDPで計算する。
dp[i]: 長さが i+1 であるような増加部分列における最終要素の最小値(存在しない場合はINF)
初期値: dp[i] = INF
数列の要素 a[j] を前から見ていき、各 a[j] に対して i = 0 もしくは dp[i-1] < a[j] となる最大の i を見つけて dp[i] = a[j]
最終的に dp[i] がINFではない最大の i+1 がLISの長さとなる
コード例(Python)
長さ $ \small N $ の数列 $ \small A $ が与えられたときのLISを求めるプログラム。計算量は $ \small O(N\log{N}) $。
def solve(n, a):
dp = [INFTY for _ in range(n)]
ans = 0
for i in range(n):
ai = a[i]
idx = bisect_left(dp, ai)
if idx < n:
dp[idx] = ai
ans = max(ans, idx)
return ans + 1
ディスカッション
コメント一覧
まだ、コメントがありません