Algoritmo: la diferencia entre dos cadenas

Este tipo de problema se puede resolver con la ayuda de la programación dinámica, donde la cadena 1 se usa como eje xy la cadena 2 se usa como eje y

Para resumir, dos cadenas admiten cuatro operaciones, a saber, agregar, modificar, eliminar y cambiar

1. Editar problema de distancia

72. Editar distancia

给你两个单词 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')

Con la ayuda de esta imagen, puede comprender mejor:
Inserte la descripción de la imagen aquí

La distancia de edición admite operaciones de inserción, eliminación y reemplazo. Establecemos una ecuación de programación dinámica dp [i] [j] para representar la coincidencia de la cadena en las posiciones i-1 y j-1, que se puede dividir en dos casos

cs1 [i-1] == cs2 [j-1], indicando que la cadena coincide y no necesita ser editada, entonces:

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

cs1 [i-1]! = cs2 [j-1], se necesita la operación de inserción, eliminación y reemplazo. ¿Cuál es mejor? Debemos calcular el valor mínimo y luego el paso +1.

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

¿Cómo determinar el estado inicial de la ecuación de programación dinámica?
Sabemos que solo hay una posibilidad para cambiar de una cadena vacía a una determinada cadena, que es agregar caracteres, por lo tanto, la primera fila y la primera columna del arreglo son iguales a los valores de fila y columna correspondientes.

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

En este punto, el problema está resuelto:

    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. El problema de subsecuencia común más largo

Reprimido reprim 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
输入的字符串只含有小写英文字符。

La siguiente imagen se obtuvo de otro lugar para ilustrar la solución a este problema. La diferencia con la distancia de edición es que no se pueden agregar caracteres en este título, solo se pueden eliminar caracteres, por lo que la primera fila y la primera columna de la matriz son ambas 0, y en la distancia de edición, ya que se pueden agregar cadenas, la primera fila es la primera Las columnas son todas 1 (excepto el elemento de posición 0, 0).
Inserte la descripción de la imagen aquí
Solo hay una operación de eliminación en esta pregunta

Sea dp [i] [j] la longitud de cuerda más larga de la cuerda en la posición i y j, entonces se puede ver que si cs [i-1] == cs [j-1], entonces la posición (i, El valor de j) dp [i] [j] = dp [i-1] [j-1] +1
De lo contrario, dp [i] [j] = Math.max (dp [i-1] [j], dp [i] [j-1]). Eso es borrar un personaje

De esto podemos concluir

    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. Diferentes subsecuencias

115. Diferentes subsecuencias

给定一个字符串 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
    ^^^

Esta pregunta es exactamente la misma que las dos preguntas anteriores, pero la condición se cambia para eliminar solo o no eliminar.

¿Qué pasa si no se borra?

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

¿Cuál es la situación con la eliminación?

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

Si los caracteres correspondientes a las dos posiciones son los mismos, podemos optar por eliminar o no eliminar, así:

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];
    }

Supongo que te gusta

Origin blog.csdn.net/qq_23594799/article/details/105340048
Recomendado
Clasificación