【LeetCode】1092. 最短共通超列(ハード) - 最長共通部分列

[トピックリンク]

https://leetcode.cn/problems/shortest-common-supersequence/

【トピックの主な考え方】

2 つの文字列str 1 str1が与えられた場合s tr 1およびstr 2str2s t r 2、2 つの中で最も短い共通スーパーシーケンスを見つけます。パブリック スーパーシーケンスの定義は、パブリック サブシーケンスの逆であり、 str 1 str1
のような最短のシーケンスを必要とします。s tr 1およびstr 2str2s t r 2 はすべてそのサブシーケンスです。
注: 答えは一意ではありません。構築されたシーケンスが条件を満たしている限り、期待される結果をデバッグし続ける必要はありません (これは私自身のことです)。

【入力例】

入力: str1 = "abac"、str2 = "cab"
出力: "cabac"
説明:
str1 = "abac" は "cabac" の部分文字列です。これは、"cabac" の最初の "c" を削除して "abac" を取得できるためです。 」。
str2 = "cab" は "cabac" の部分文字列です。これは、"cabac" の末尾の "ac" を削除すると "cab" を取得できるためです。
最終的に、私たちが与える答えは、上記の特性を満たす最も短い文字列です。

【データ範囲】

1 <= str1.length、str2.length <= 1000
str1 と str2 は両方とも小文字の英字で構成されます。


最長共通部分列 + 構築

  実際、その方法を考えるのは難しいことではなく、それをどのように実現するかが難しいのです。タイトルの意味からも想像できる通り、str1 str1なのでs tr 1およびstr 2str2s t r 2 がこのスーパー シーケンスの部分文字列である場合、最初にstr 1 str1s tr 1およびstr 2str2s t r 2の最長の共通部分シーケンス次に問題が発生します。部分シーケンスは部分文字列と同じではありません。部分文字列は連続しているため、直接連結できます。ただし、サブシーケンスは不連続になる可能性があります。このスーパーシーケンスがstr 1 str1s tr 1およびstr 2str2s t r 2の 2 つの部分列はどうなるでしょうか答えは、最長の共通部分列内の配列から推測することです。
  最長共通部分列の漸化式は、 dp [ i ] [ j ] = { 0 i = 0 または j = 0 dp [ i − 1 ] [ j − 1 ] + 1 str 1 [ i − 1 ] = str 2 [ j − 1 ] max ⁡ ( dp [ i − 1 ] [ j ] , dp [ i ] [ j − 1 ] ) str 1 [ i − 1 ] ≠ str 2 [ j − 1 ] dp[i][j] = \begin{cases}0&i=0\text{ または }j=0\\ dp[i-1][j-1]+1&str1[i-1]=str2[j-1]\\ \max(dp [ i-1][j],dp[i][j-1])&str1[i-1]\neq str2[j-1]\end{cases}d p [ i ] [ j ]= 0d p [ i1 ] [ j1 ]+1最大( d p [ i1 ] [ j ] d p [ i ] [ j1 ] )=0 または j=0s tr 1 [ i _1 ]=s t r 2 [ j1 ]s tr 1 [ i _1 ]=s t r 2 [ j1 ]
この動的プログラミング配列を実行した後、ダブル ポインターiiを使用します。JJj前に後ろに押す

  • 結果dp [ i ] [ j ] = dp [ i − 1 ] [ j − 1 ] + 1 dp[i][j]=dp[i-1][j-1]+1d p [ i ] [ j ]=d p [ i1 ] [ j1 ]+1は、現在の文字がパブリック パーツであることを示します。str 1 [ i ] str1[i]s tr 1 [ i ]またはstr 2 [ j ] str2[j ]s t r 2 [ j ]結合結果文字列
  • 結果dp [ i ] [ j ] = dp [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j]d p [ i ] [ j ]=d p [ i1 ] [ j ]str 1 [ i ] str1[i]s t r 1 [ i ]は最長共通部分列、つまり異なる部分には寄与しないため、str 1 [ i ] str1[i]st r 1 [ i ]結合_
  • 同様に、dp [ i ] [ j ] = dp [ i ] [ j − 1 ] の場合、 dp[i][j]=dp[i][j-1]d p [ i ] [ j ]=d p [ i ] [ j1 ]str 2 [ j ] str2[j]st r 2 [ j ]結合_

同時に、両者の長さが異なる可能性があるため、境界の問題も考慮する必要があり、一方を比較した後、もう一方の残りの文字を末尾に直接追加します。

class Solution {
    
    
public:
    string shortestCommonSupersequence(string str1, string str2) {
    
    
        int m=str1.length(),n=str2.length();
        vector<vector<int>> dp(m+1,vector<int> (n+1,0));
        //求最长公共子序列
        for(int i=1;i<=m;++i){
    
    
            for(int j=1;j<=n;++j){
    
    
                if(str1[i-1]==str2[j-1]) dp[i][j]=dp[i-1][j-1]+1;
                else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            }
        }
        int i=m,j=n;
        string res;
        while(i||j){
    
    
            if(i==0) res=str2[--j]+res;//str1已结束
            else if(j==0) res=str1[--i]+res;//str2已结束
            else{
    
    
            //分别对应上述的三种情况
                if(dp[i][j]==dp[i-1][j]) res=str1[--i]+res;
                else if(dp[i][j]==dp[i][j-1]) res=str2[--j]+res;
                else res=str1[--i]+res,--j;
            }
        }
        return res;
    }
};

おすすめ

転載: blog.csdn.net/qq_44623371/article/details/129812420