アルゴリズム-2つの文字列の違い

このタイプの問題は、文字列1がx軸として使用され、文字列2がy軸として使用される動的プログラミングの助けを借りて達成できます。

要約すると、2つの文字列は、追加、変更、削除、および変更の4つの操作をサポートします。

1.距離の問題を編集する

72.距離を編集する

给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
 

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

この写真の助けを借りて、あなたはよりよく理解することができます:
ここに写真の説明を挿入

編集距離は、挿入、削除、および置換操作をサポートします。動的プログラミング方程式dp [i] [j]を確立して、i-1およびj-1位置での文字列のマッチングを表します。これは、2つのケースに分けることができます。

cs1 [i-1] == cs2 [j-1]は、文字列が一致し、編集する必要がないことを示します。

dp[i][j]=dp[i-1][j-1]

cs1 [i-1]!= cs2 [j-1]の場合、挿入、削除、および置換の操作を実行する必要があります。どちらが優れていますか?最小値を計算してから、ステップ+1を実行する必要があります。

dp[i][j]=Math.min(dp[i-1][j-1],Math.min(dp[i-1][j],dp[i][j-1]))+1;

動的プログラミング方程式の初期状態を決定する方法は?
空の文字列から特定の文字列に変更する可能性は、文字を追加することだけであることがわかっています。したがって、配列の最初の行と最初の列は、対応する行と列の値と等しくなります。

...
dp[i][0]=i;
...
dp[0][j]=j;
...

これまでのところ、問題は解決されています。

    public int minDistance(String word1, String word2) {
    
    
        char[] cs1=word1.toCharArray();
        char[] cs2=word2.toCharArray();
        int[][] dp=new int[cs1.length+1][cs2.length+1];
        for(int i=0;i<=cs1.length;i++){
    
    
            dp[i][0]=i;
        }
        for(int j=0;j<=cs2.length;j++){
    
    
            dp[0][j]=j;
        }

        for(int i=1;i<=cs1.length;i++){
    
    
            for(int j=1;j<=cs2.length;j++){
    
    
                if(cs1[i-1]==cs2[j-1]){
    
    
                    dp[i][j]=dp[i-1][j-1];
                }else{
    
    
                    dp[i][j]=Math.min(dp[i-1][j-1],Math.min(dp[i-1][j],dp[i][j-1]))+1;
                }
            }
        }
        return dp[cs1.length][cs2.length];
    }

2.最も長い一般的なサブシーケンスの問題

1143.最長の共通サブシーケンス

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。

若这两个字符串没有公共子序列,则返回 0。

示例 1:
输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace",它的长度为 3。
示例 2:

输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc",它的长度为 3。
示例 3:

输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0。
 

提示:

1 <= text1.length <= 1000
1 <= text2.length <= 1000
输入的字符串只含有小写英文字符。

以下の写真は、この問題の解決策を説明するために他の場所から撮影したものです。編集距離との違いは、このタイトルには文字を追加できず、削除できるのは文字のみであるため、配列の最初の行と最初の列は両方とも0であり、編集距離では、文字列を追加できるため、最初の行が最初になります列はすべて1です(0、0の位置要素を除く)。
ここに写真の説明を挿入
この質問には削除操作のみがあります

dp [i] [j]を位置iとjの文字列の最長文字列長とすると、cs [i-1] == cs [j-1]の場合、位置(i、 jの値)dp [i] [j] = dp [i-1] [j-1] +1
それ以外の場合、dp [i] [j] = Math.max(dp [i-1] [j]、dp [i] [j-1])。それは文字を削除することです

これから結論を出すことができます

    public int longestCommonSubsequence(String text1, String text2) {
    
    
        char cs1[]=text1.toCharArray();
        char cs2[]=text2.toCharArray();
        int[][] dp=new int[cs1.length+1][cs2.length+1];
        for(int i=1;i<=cs1.length;i++){
    
    
            for(int j=1;j<=cs2.length;j++){
    
    
                if(cs1[i-1]==cs2[j-1]){
    
    
                    dp[i][j]=dp[i-1][j-1]+1;
                }else{
    
    
                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        return dp[cs1.length][cs2.length];
    }

3.さまざまなサブシーケンス

115.さまざまなサブシーケンス

给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数。

一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)

 

示例 1:

输入:S = "rabbbit", T = "rabbit"
输出:3
解释:

如下图所示, 有 3 种可以从 S 中得到 "rabbit" 的方案。
(上箭头符号 ^ 表示选取的字母)

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^
示例 2:

输入:S = "babgbag", T = "bag"
输出:5
解释:

如下图所示, 有 5 种可以从 S 中得到 "bag" 的方案。 
(上箭头符号 ^ 表示选取的字母)

babgbag
^^ ^
babgbag
^^    ^
babgbag
^    ^^
babgbag
  ^  ^^
babgbag
    ^^^

この質問は上記の2つの質問とまったく同じですが、条件が削除のみまたは削除しないように変更されています。

削除しないとどうなりますか?

dp[i][j]=dp[i-1][j-1];

削除の状況はどうですか?

p[i][j]=dp[i][j-1];

2つの位置に対応する文字が同じである場合、削除するか削除しないかを選択できます。

dp[i][j]=dp[i-1][j-1]+dp[i][j-1];
    public int numDistinct(String s, String t) {
    
    
        int len1=s.length();
        int len2=t.length();
        int [][]dp=new int[len2+1][len1+1];
        for(int i=0;i<=len1;i++){
    
    
            dp[0][i]=1;//第一行为1,因为删除字符得到空字符
        }
        char[] cs=s.toCharArray();
        char[] ct=t.toCharArray();
        for(int i=1;i<=len2;i++){
    
    
            for(int j=1;j<=len1;j++){
    
    
                if(cs[j-1]==ct[i-1]){
    
    
                    dp[i][j]=dp[i-1][j-1]+dp[i][j-1];
                }else{
    
    
                    dp[i][j]=dp[i][j-1];
                }
            }
        }
        return dp[len2][len1];
    }

おすすめ

転載: blog.csdn.net/qq_23594799/article/details/105340048