C++で2つの文字列を一致させるための最小削除操作数を求めるアルゴリズム
2つの単語 w1 と w2 が与えられたとき、各ステップでどちらかの文字列から1文字を削除できるものとして、w1 と w2 を同一にするまでに必要な最小ステップ数を求める問題を考えてみましょう。
例えば、入力が「sea」と「eat」の場合、出力は 2 になります。これは、w1 から「s」を削除して「ea」にし、さらに w2 である「eat」から「t」を削除することで、両方とも「ea」になり一致するからです。
解決のアプローチ
この問題は動的計画法(DP)を用いて効率的に解くことができます。以下の手順に従います。
- n := s1 の長さ、m := s2 の長さとします
- s1 と s2 の先頭にそれぞれ空白を1つ追加し、インデックスを1始まりに調整します
- (n + 1) × (m + 1) のサイズを持つDPテーブルを作成します
- i = 1 から m まで:dp[0, i] := dp[0, i - 1] + 1(空文字列との比較では全文字を削除する必要がある)
- i = 1 から n まで:dp[i, 0] := dp[i - 1, 0] + 1
- i = 1 から n、j = 1 から m までの二重ループで以下を処理します:
- s1[i] == s2[j] の場合:dp[i, j] := dp[i - 1, j - 1](文字を削除する必要がない)
- それ以外の場合:dp[i, j] := min(dp[i - 1, j] + 1, dp[i, j - 1] + 1)(どちらかの側から1文字削除する)
- 最後に dp[n, m] を返します
C++による実装例
理解を深めるために、以下の実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int minDistance(string s1, string s2) {
int n = s1.size();
int m = s2.size();
s1 = " " + s1;
s2 = " " + s2;
vector<vector<int>> dp(n + 1, vector<int>(m + 1));
for(int i = 1; i <= m; i++){
dp[0][i] = dp[0][i - 1] + 1;
}
for(int i = 1; i <= n; i++){
dp[i][0] = dp[i - 1][0] + 1;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s1[i] == s2[j]){
dp[i][j] = dp[i - 1][j - 1];
}
else{
dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
}
}
}
return dp[n][m];
}
};
main(){
Solution ob;
cout << (ob.minDistance("sea", "eat"));
}
入力
"sea" "eat"
出力
2
このアルゴリズムの時間計算量は O(n × m)、空間計算量も O(n × m) となります。共通部分列(LCS)の考え方を応用した手法であり、「sea」と「eat」の場合、最長共通部分列は「ea」(長さ2)なので、削除が必要な文字数は (3 - 2) + (3 - 2) = 2 となります。
-
C++で2つの2進数文字列を加算するプログラムの書き方
2つの2進数を表す文字列が与えられたとき、それらを加算した結果を求め、その結果を2進数の文字列として返すことを考えます。2進数とは、0か1のいずれかで表現される数値のことです。2進数同士を足し合わせる際には、以下のような2進数特有の加算ルールに従う必要があります。0+0 → 0 0+1 → 1 1+0 → 1 1+1 → 0(繰り上がり1)入力例str1 = {11}, str2 = {1}出力例100入力例str1 = {110}, str2 = {1}出力例111問題を解くためのアプローチ両方の文字列を末尾(最下位桁)から走査する対応する桁の2進数同士を加算する1と1を足した場合は、その桁
-
C++で2本の直線の交点を求めるプログラムの書き方
直線ABを定義する2点A・Bと、直線CDを定義する2点C・Dが与えられたとき、この2つの直線の交点を求めるのが課題です。 注意 − すべての点は、X座標とY座標を持つ2次元平面上にあるものとします。 図では、A(a1, a2)とB(b1, b2)を通る直線、C(c1, c2)とD(d1, d2)を通る直線という、互いに異なる2つの直線が描かれており、P(p1, p2)がその交点を表しています。 交点の求め方 まず、2点を通る直線を「ax + by = c」の形の方程式で表します。各点の座標を使って、次のように係数を計算します。 A1 = b2 - a2 B1 = a1 - b1 C1 =