Pythonで2つの文字列を含む最短スーパーシーケンス(共通超系列)の長さを求めるプログラム
2つの文字列 s と t が与えられたとき、s と t の両方を部分列として含む最短の文字列(最短共通スーパーシーケンス)の長さを求める問題を考えてみましょう。
例えば、入力が s = "pipe"、t = "people" の場合、答えは 7 になります。これは「pieople」という文字列が、両方の文字列を部分列として含む最短の例の一つだからです。
解法の考え方:LCS(最長共通部分列)を利用する
この問題は動的計画法(DP)を使って効率的に解けます。ポイントとなるのは次の関係式です。
最短スーパーシーケンスの長さ = len(s) + len(t) − LCS(s, t)
つまり、まず2つの文字列の最長共通部分列(LCS)の長さを求めておけば、共通する部分を1回だけ使うことで、全体の長さからその分を差し引いたものが答えになります。
アルゴリズムの手順
- m を s の長さ、n を t の長さとします。
- (m + 1) × (n + 1) のサイズの2次元表 table を用意し、すべて 0 で初期化します。
- i を 0 から m まで、j を 0 から n まで順に走査します。
- i が 0 または j が 0 の場合は table[i][j] = 0 とします(どちらかの文字列が空の場合、LCSは0)。
- s[i - 1] と t[j - 1] が一致する場合は、table[i][j] = 1 + table[i - 1][j - 1] とします(共通の文字を見つけたのでLCSが1増える)。
- それ以外の場合は、table[i][j] = max(table[i][j - 1], table[i - 1][j]) とします(片方の文字列の末尾を無視した場合の最大値を採用)。
- 最後に m + n − table[m][n] を返します。これが最短スーパーシーケンスの長さです。
Pythonでの実装例
以下に実際のコードを示します。
class Solution:
def solve(self, s, t):
m = len(s)
n = len(t)
# (m+1) x (n+1) のDPテーブルを0で初期化
table = [[0 for i in range(n + 1)] for j in range(m + 1)]
for i in range(m + 1):
for j in range(n + 1):
if i == 0 or j == 0:
table[i][j] = 0
else:
if s[i - 1] == t[j - 1]:
# 文字が一致:LCSが1つ伸びる
table[i][j] = 1 + table[i - 1][j - 1]
else:
# 一致しない場合:より大きい方を採用
table[i][j] = max(table[i][j - 1], table[i - 1][j])
return m + n - table[m][n]
ob = Solution()
s = "pipe"
t = "people"
print(ob.solve(s, t))入力
"pipe", "people"
出力
7
計算量について
このアルゴリズムの時間計算量は O(m × n)、空間計算量も O(m × n) です。2つの文字列の長さの積に比例するため、比較的短い文字列に対しては十分高速に動作します。
-
Pythonでポリゴンの面積を求める方法:靴ひも公式を使った実装
はじめに2次元平面上に、単純な多角形(ポリゴン)の頂点を時計回りまたは反時計回りの順に並べた座標リストが与えられたとします。このとき、その多角形の面積を計算するのが本記事の目的です。例えば、入力が points = [(0, 0), (0, 5), (3, 5), (3, 0)] のような場合、これは幅3・高さ5の長方形を表しているため、出力は 15.0 となります。解法の考え方:靴ひも公式(Shoelace Formula)この問題は、有名な靴ひも公式(測量士の公式)を使うことで効率的に解けます。隣り合う2頂点ごとに外積 x1*y2 - y1*x2 を計算し、それらをすべて足し合わせて絶対値
-
Pythonでターゲットノードを含む最短サイクルの長さを求める方法(BFS活用)
問題の概要有向グラフの隣接リストが与えられます。各インデックス i のリストには、ノード i から直接接続されているノードの一覧が格納されています。さらに、探索対象となる値(target)も与えられます。この課題では、target を含むサイクル(閉路)の中で最も短いものの長さを求めます。該当するサイクルが存在しない場合は -1 を返してください。具体例例えば、次のようなグラフが与えられたとします。graph = [[1, 4], [2], [3], [0, 1], []]target = 3 の場合、出力は 3 になります。これは、ノード 1 → 2 → 3 → 1 というサイクルが存在する