4. LCS(Longest Common Subsequence)
¨ 最長共通部分列問題
¤ 与えられた 2 つの列 X = ⟨x1,x2,...,xm⟩と
Y =⟨y1,y2,...,yn⟩の最長共通部分列を求める問題
¨ 例)
¤ X = <A, B, C, B, D, A, B>
¤ Y = <B, D, C, A, B, A>
¤ LCS = <B, C, B, A>
¤ LCSは1つとは限らない!
n <B, C A, B>もLCSの解
n LCSが変わるとSESも変わる
4
18. k-candidates
18
0 1 2 2 3 3 4 4
0 1 2 2 3 3 3 4
0 1 1 2 2 2 3 3
0 0 1 2 2 2 2 2
0 0 1 1 1 2 2 2
0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0
B
B
C
D
A
BDBCBA A
A
A B C B D A B
A
B
A
C
D
B
¨ Ai = Bj
¨ Pij > max(Pi−1, j , Pi, j−1 )
19. k-candidatesを繋げる
19
0 1 2 2 3 3 4 4
0 1 2 2 3 3 3 4
0 1 1 2 2 2 3 3
0 0 1 2 2 2 2 2
0 0 1 1 1 2 2 2
0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0
B
B
C
D
A
BDBCBA A
A
A B C B D A B
A
B
A
C
D
B
¨ k-candidatesの左下にあるCandidateから最長のも
のを接続する。
¨ 実装によって実際に接続されるものが異なる
20. 実装コード
20
¨ diff-lcs
¤ Rubyのdiffを求めるためのGem
¤ Hunt-Mcllroyのアルゴリズムを用いて実装
¤ 片方をまずハッシュ化する
n 例) ABCBDAB
n {' A' : [0, 5],' B' : [1, 3, 6],' C' : [2],' D' : [4]}
¨ https://github.com/halostatue/diff-lcs/blob/
master/lib/diff/lcs/internals.rb#L41
22. diff-lcsに触れる
22
require 'diff/lcs'
seq1 = %w(a b c e h j l m n p)
seq2 = %w(b c d e f j k l m r s t)
lcs = Diff::LCS.LCS(seq1, seq2)
diffs = Diff::LCS.diff(seq1, seq2)
sdiff = Diff::LCS.sdiff(seq1, seq2)
seq = Diff::LCS.traverse_sequences(seq1, seq2, callback_obj)
bal = Diff::LCS.traverse_balanced(seq1, seq2, callback_obj)
seq2 == Diff::LCS.patch!(seq1, diffs)
seq1 == Diff::LCS.unpatch!(seq2, diffs)
seq2 == Diff::LCS.patch!(seq1, sdiff)
seq1 == Diff::LCS.unpatch!(seq2, sdiff)