DP (una forma de KO tres problemas difíciles de DP, me siento muy bien) 72. Distancia de edición 97. Cadena intercalada 44. Coincidencia de comodines 10. Coincidencia de expresiones regulares

72. Editar distancia

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

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

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

(Esta pregunta también es una pregunta de entrevista aprobada por el byte de antemano) Al principio pensé en encontrar la subsecuencia común más larga de dos cadenas, estas no cambiarán, y luego usaré la más larga para reducirla, que debe cambiarse El número mínimo de operaciones, este método notó el problema de la desalineación al pensar, pero no pensó bien, como a ** by * a * b, mi respuesta es 4-2 = 2, pero de hecho a * * b debe pasar por 3 operaciones para convertirse en * a * b. Entonces, esta pregunta es la más fácil y sencilla de registrar el número de revisiones necesarias.

La ecuación de transferencia es similar a la subsecuencia común más larga, pero pueden pensar en ella juntos.

f[i][j]=min(min(f[i-1][j]+1,f[i][j-1]+1),word1[i-1]==word2[j-1]?f[i-1][j-1]:f[i-1][j-1]+1);
class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1=word1.length(),len2=word2.length();
        int f[len1+10][len2+10];
        memset(f,0,sizeof(f));
        for (int j=1;j<=len2;++j)
        {
            f[0][j]=j;
        }
         for (int i=1;i<=len1;++i)
        {
            f[i][0]=i;
        }
        for (int j=1;j<=len2;++j)
            for (int i=1;i<=len1;++i)
            {
                f[i][j]=min(min(f[i-1][j]+1,f[i][j-1]+1),word1[i-1]==word2[j-1]?f[i-1][j-1]:f[i-1][j-1]+1);
            }
            
        return f[len1][len2];
    }
};

97. Cadenas intercaladas

Aquí hay una inserción del mismo tipo de problema de coincidencia de cadenas. También es una definición directa de si f [i] [j] es s1 [0..i-1] y s2 [0..j-1] se puede intercalar para formar s3 [ 0..i + j-1], y finalmente f [lente] [lenp] es la respuesta.

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        int len1=s1.length(),len2=s2.length(),len3=s3.length();
        if (len1+len2!=len3) return false;
        vector<vector<bool>> f(len1+10,vector<bool>(len2+10,false));
        f[0][0]=true;
        for (int i=1;i<=len1;i++)
        if (s1[i-1]==s3[i-1]) f[i][0]=f[i-1][0];
        for (int j=1;j<=len2;j++)
        if (s2[j-1]==s3[j-1]) f[0][j]=f[0][j-1];

        for (int i=1;i<=len1;i++)
        for (int j=1;j<=len2;j++)
        {
            if (s1[i-1]==s3[i+j-1]) f[i][j]=f[i-1][j];
            if (s2[j-1]==s3[i+j-1]) f[i][j]=f[i][j] || f[i][j-1];
        }
        return f[len1][len2];
    }
};

44. Coincidencia de comodines

La idea de esta pregunta es en realidad la misma que la anterior, f [i] [j] es registrar directamente si s [0..i-1] yp [0..j-1] pueden coincidir, y finalmente generar f [lente ] [lenp] está bien.

La edición de distancia anterior es la misma, f [i] [j] es para registrar directamente la distancia de edición de s [0..i-1] yp [0..j-1], y finalmente generar f [lente] [lenp] Pero se puede decir exactamente lo mismo.

Por supuesto, las condiciones de límite iniciales de estas dos preguntas son diferentes, por lo que debe explorar y depurar usted mismo.

class Solution {
public:
    bool isMatch(string s, string p) {
        int lens=s.length(),lenp=p.length();
        if (lens==0 && lenp==0) return true;
        if (lenp==0) return false;
        bool f[lens+10][lenp+10];
        memset(f,0,sizeof(f));
        f[0][0]=true;
        int index=0;
        while (index<lenp && p[index]=='*') {f[0][++index]=true;}
        for (int j=1;j<=lenp;j++)
            for (int i=1;i<=lens;i++)   
            {
                if (s[i-1]==p[j-1] || '?'==p[j-1]) f[i][j]=f[i-1][j-1];
                else 
                {
                    if ('*'==p[j-1]) f[i][j]=f[i-1][j] || f[i][j-1];
                    else 
                    f[i][j]=false;
                }
            }
        return f[lens][lenp];
    }
};

Además, se adjunta una solución oficial: https://leetcode-cn.com/problems/wildcard-matching/solution/tong-pei-fu-pi-pei-by-leetcode-solution/

El segundo método en el interior describe el algoritmo codicioso, que ahorra espacio y gastos generales en comparación con la programación dinámica , y hay una discusión sobre los autómatas de CA más adelante , y tengo tiempo para mirarlo.

Tengamos una versión avanzada a continuación y la dificultad aumentará.

10. Coincidencia de expresiones regulares

Cualquier carácter en el patrón p no es independiente y se asociará con los caracteres anteriores (posteriores) para formar un nuevo patrón coincidente. Por lo tanto, la ecuación de transición de estado de este problema debe considerarse más. Después de pensarlo brevemente, ". *" Puede coincidir con ab, lo que equivale a cero o más "." S. El efecto de ". **" es en realidad el mismo, es decir, varios "*" no tienen sentido. En este momento, encontramos que un solo "." Es equivalente al "?" Anterior, y ". * 'Es equivalente al" * "anterior, varios" * "se pueden simplificar en un" * ". Ahora la última pregunta Es cómo lidiar con "a *", y luego descubrimos que cada vez que aparece '*', definitivamente tenemos que considerar * el anterior, la solución es lidiar con *, estamos aquí para juzgar si i + 1 es * actual de procesamiento, sí El mismo efecto.

Pero una de las respuestas estándar no se ha tratado correctamente: es decir, establece de forma predeterminada que las expresiones regulares no comienzan con "*" ( las expresiones regulares que comienzan con * son ilegales, es decir, no hay ninguna expresión regular que comience con *), de lo contrario sucederá La matriz está fuera de límites. Lo he estado procesando durante mucho tiempo y es básicamente de la misma manera que los comodines.

class Solution {
public:
    bool isMatch(string s, string p) {
        int lens=s.length(),lenp=p.length();
        if (lens==0 && lenp==0) return true;
        if (lenp==0) return false;
        bool f[lens+10][lenp+10];
        memset(f,0,sizeof(f));
        f[0][0]=true;
        //int index=0;
        //while (index<lenp && p[index]=='*') {f[0][++index]=true;}
        //if (index==lenp) return false;    

        for (int j=1;j<=lenp;j++)
            for (int i=0;i<=lens;i++)
            {
                if (p[j-1]=='*')
                {
                    f[i][j] = f[i][j-2];
                    if (i>0 && (p[j-2]==s[i-1] || p[j-2]=='.'))
                        f[i][j] |=f[i-1][j];
                }
                else
                {
                    if (i>0 && (p[j-1]==s[i-1] || p[j-1]=='.'))
                        f[i][j] = f[i-1][j-1];
                    else 
                        f[i][j]=false;

                    
                }
            }
            return f[lens][lenp];

        
    }
};

Este método de escritura es mejor, porque se juzga a partir de *. 1. Es relativamente conciso, 2. Puede manejar el problema de inicialización de i = 0, 3. Cuando se procesa un * de a por separado, aunque se realiza una conversión no válida, se procesa para un * * Cuando se transfiere desde j-2, no afecta. El problema de ** no se considera aquí, por lo que, de hecho, la inicialización puede eliminar el * al principio de la cadena p y eliminar el * continuo .

Aquí hay un registro de las características nuevas y nuevas de C ++ 11, es decir, expresiones lamda. No es necesario escribir una función grande fuera de la función ,,,

auto matches = [&](int i, int j) 
{
    if (i == 0) 
        return false;
    if (p[j - 1] == '.') 
        return true;
    return s[i - 1] == p[j - 1];
};

Utilice la expresión Lambda que captura todo por referencia. La estructura de la expresión Lambda [lista de captura] (parámetros) -> tipo de retorno {definición de método} utilizará algunas variables externas internamente. Esto se llama captura y se puede escribir explícitamente en [] Dentro, también se pueden capturar implícitamente. Hay diferentes situaciones en [], vacío significa que no hay captura, [=] significa capturar todo por copia y [&] significa capturar todo por referencia. Para obtener más información, consulte

https://www.cnblogs.com/kekec/p/10904802.html

continuará......

 

Supongo que te gusta

Origin blog.csdn.net/hbhhhxs/article/details/107759285
Recomendado
Clasificación