C++における二つの文字列の最長部分文字列を見つける方法


最もシンプルで効率的な方法は、動的計画法(Dynamic Programming)を使用することです。以下に、具体的な手順を示します。

  1. 二次元の配列dpを用意します。dp[i][j]は、最長部分文字列の長さを表します。ここで、iは最初の文字列のインデックス、jは二つ目の文字列のインデックスを表します。

  2. dpの要素を初期化します。dp[i][j]は、二つの文字列のi番目とj番目の文字が一致する場合は1、そうでない場合は0とします。

  3. 二重ループを使用して、dpの要素を計算します。iとjを1から文字列の長さまで順に増やしながら、以下の漸化式を適用します。

    • もし、二つの文字列のi番目とj番目の文字が一致する場合(つまり、文字列が共通している場合)、dp[i][j] = dp[i-1][j-1] + 1とします。
    • そうでない場合は、dp[i][j] = 0とします。
  4. dpの要素の中で最大値を求めます。これが最長部分文字列の長さになります。

  5. 最長部分文字列の長さを使用して、元の文字列から最長部分文字列を抽出します。

以下は、上記の手順を具体的なコード例で示したものです。

#include <iostream>
#include <string>
std::string findLongestSubstring(const std::string& str1, const std::string& str2) {
    int len1 = str1.length();
    int len2 = str2.length();
    int maxLen = 0;
    int endIndex = 0;
    // 二次元配列dpの初期化
    int dp[len1 + 1][len2 + 1] = {0};
    // dpの計算
    for (int i = 1; i <= len1; i++) {
        for (int j = 1; j <= len2; j++) {
            if (str1[i - 1] == str2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
                if (dp[i][j] > maxLen) {
                    maxLen = dp[i][j];
                    endIndex = i - 1;
                }
            }
        }
    }
// 最長部分文字列の抽出
    std::string longestSubstring = str1.substr(endIndex - maxLen + 1, maxLen);
    return longestSubstring;
}
int main() {
    std::string str1 = "abcdef";
    std::string str2 = "defgabc";
    std::string longestSubstring = findLongestSubstring(str1, str2);
    std::cout << "最長部分文字列: " << longestSubstring << std::endl;
    return 0;
}

上記のコードでは、文字列"abcdef"と"defgabc"の最長部分文字列を求める例を示しています。最長部分文字列は"abc"です。

この方法を使用することで、二つの文字列の最長部分文字列を見つけることができます。