2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LCS(最長共通部分列)をPythonで解く

Posted at

この記事でやること

前回の記事で、2つの文字列の類似度を表すレーベンシュタイン距離ジャロ・ウィンクラー距離について説明した。

2つの文字列の一致度を表すものとして、他に最長共通部分列(Longest Common Subsequence: LCS)がある。
今回の記事はこのLCSの紹介をした後にPythonを使って実装してみる。

LCSとは?

定義は簡単で、単に二つの文字列の共通部分を表す。
この共通部分は必ずしも連続した文字である必要はなく、例えば"aa"と"xayaz"のLCSは"aa"となる。

この実装は競プロではお馴染みのdp (dynamic programming)で解けることが知られている。

解いてみる

AtCoderの過去の問題でちょうどいい問題があったのでPythonで解いてみる。

str1 = input()
str2 = input()
dp = [[0] * (len(str2)+1) for i in range(len(str1)+1)]

for i, vi in enumerate(str1):
    for j, vj in enumerate(str2):
        if vi == vj:
            dp[i+1][j+1] = dp[i][j] + 1
        else:
            dp[i+1][j+1] = max(dp[i+1][j], dp[i][j+1])
#print(dp[len(str1)][len(str2)])

ans = []
i = len(str1) - 1
j = len(str2) - 1
while i >= 0 and j >= 0:
    if str1[i] == str2[j]:
        ans.append(str1[i])
        i -= 1
        j -= 1
    elif dp[i+1][j+1] == dp[i][j+1]:
        i -= 1
    elif dp[i+1][j+1] == dp[i+1][j]:
        j -= 1
ans.reverse()
print(*ans, sep='')

最初のenumerateのloopでdpを計算し、それを用いて2回目のwhileのloopで共通する文字列を計算している。
単に"最大で何文字共通するか"だけを知りたければ最初のloopの後にdpを出力すれば求まる。

この値が大きいほど「共通部分が大きい = 2つも文字列が類似している」とイメージできそうだ。

まとめ

  • 最長共通部分列 (LCS)について紹介した
  • LCSはdpを使って計算することができる
2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?