Sword se refiere a la oferta 19. Coincidencia de expresiones regulares

1. Descripción del tema

Implemente una función para que coincida con las expresiones regulares que contienen '.' y "*". El carácter '.' en el modo significa cualquier carácter, y "*" significa que el carácter que está delante de él puede aparecer cualquier número de veces (incluidas 0 veces). En esta pregunta, coincidencia significa que todos los caracteres de la cadena coinciden con el patrón completo. Por ejemplo, la cadena "aaa" coincide con los patrones "aa" y "ab*ac*a", pero no con "aa.a" ni con "ab*a".

Ejemplo 1

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

Ejemplo 2

输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

Ejemplo 3

输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。

Ejemplo 4

输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。

Ejemplo 5

输入:
s = "mississippi"
p = "mis*is*p*."
输出: false

2. Solución: programación dinámica

Ideas y Algoritmos

La coincidencia en el título es un proceso de "coincidencia paso a paso": cada vez que comenzamos desde la cadena ppSaque un carácter o una combinación de "carácter + asterisco" de p , y póngalo en sss para hacer coincidir. Para un carácter en , solo puede estar enssHaga coincidir un carácter en s , el método de coincidencia es único; y para
ppEn cuanto a la combinación de carácter + asterisco en p , se puede encontrar en sss coincide con cualquier número natural de caracteres y no es único. Por lo tanto, podemos considerar el uso de programación dinámica para enumerar los esquemas coincidentes.

Usamos f [ i ] [ j ] f[i][j]f [ i ] [ j ] significassex iide si personajes yppex jjen pSi se pueden hacer coincidir j caracteres. Al hacer transiciones de estado, consideramosppp 'sjjthCoincidencia de j caracteres:

  • si ppp 'sjjthj caracteres es una letra minúscula, entonces debemos ensss coincide con una letra minúscula idéntica, es decir

F [ yo ] [ j ] = { F [ yo − 1 ] [ j − 1 ] , s[i]=p[j] false , s[i] ≠ p[j] f[i][j]= \ begin {casos} f[i-1][j-1],&\text {s[i]=p[j]}\\ false,&\text {s[i]$\neq$p[j] } \end {casos}f [ yo ] [ j ]={ f [ yo1 ] [ j1 ] ,falso _ _ _ _ _s[i]=p[j]si]=p[j ]
Es decir, si sss segundoiii personajes yppp 'sjjthj caracteres no son iguales, entonces no se puede realizar la coincidencia; de lo contrario, podemos hacer coincidir el último carácter de las dos cadenas, y el resultado de la coincidencia completa depende de la parte anterior de las dos cadenas.

  • si ppp 'sjjthj caracteres son * entonces significa que podemosppp 'sjth − 1 j-1j1 carácter coincide con cualquier número natural de veces. En el caso de 0 coincidencias, tenemos f [ i ] [ j ] = f [ i ] [ j − 2 ] f[i][j]=f[i][j-2]f [ yo ] [ j ]=f [ yo ] [ j2 ]
    Es decir, "desperdiciamos" una combinación de caracteres + asteriscos, que no coincidía con ningunasscaracteres en s .
    En el caso de hacer coincidir 1,2,3,⋯ veces, de manera similar tenemos
    inserte la descripción de la imagen aquí
    Si transferimos a través de este método, entonces necesitamos enumerar esta combinación para hacer coincidirsss , unos pocos caracteres aumentarán la complejidad del tiempo y el código es muy engorroso de escribir. También podríamos considerar este problema desde otro ángulo: en el proceso de hacer coincidir letras + asteriscos, existen esencialmente solo dos situaciones:
    • partido ssUn carácter al final de s , el carácter se descarta y la combinación puede seguir coincidiendo;
    • No se empareja ningún carácter, la combinación se descarta y no se realiza ninguna otra coincidencia.
      Si pensamos desde esta perspectiva, podemos escribir una ecuación de transición de estado muy delicada:
      inserte la descripción de la imagen aquí
    • En cualquier caso, mientras p [ j ] p[j]p [ j ] es. , entoncesp[j] p[j]p [ j ] debe coincidir correctamentecon ssCualquier letra minúscula en s .

La ecuación de transición de estado final es la siguiente:
inserte la descripción de la imagen aquí
donde coincide con ( x , y ) coincide con (x,y)coincidencias ( x , _ _ _ _ _ _y ) Función auxiliar para juzgar si dos caracteres coinciden, solo cuandoyyy es. oxxx y y Estos dos caracteres solo coincidirán si el mismo y es el mismo.

detalle

La condición límite de la programación dinámica es f [ 0 ] [ 0 ] = truef[0][0]=truef [ 0 ] [ 0 ]=verdadero , es decir, se pueden hacer coincidir dos cadenas vacías . La respuesta final esf [ m ] [ n ] f[m][n]f [ m ] [ n ] dondemmm ynnn es la cadena ssrespectivamentes yppla longitud de p . . Debido a que en la mayoría de los idiomas, el subíndice de caracteres de una cadena comienza desde 00, por lo que al implementar la ecuación de transición de estado anterior, es necesario prestar atención a la relación correspondiente entre cada subíndice de dimensión en el estado y el subíndice de carácter real.
En la ecuación de transición de estado anterior, si la cadena p contiene una combinación de "carácter + asterisco" (como a*), entonces a coincidirá primero cuando se realice la transición de estado (cuando p [ j ] p [ j]p [ j ] es a), luego haga coincidir a* como un todo (cuandop [ j ] p[j]p [ j ] es *). Sin embargo, en la descripción del tema, debemos considerar a* como un todo, por lo que hacer coincidir a no cumple con los requisitos del tema.

3. Fragmento de código

class Solution {
    
    
public:
   bool isMatch(string s, string p) {
    
    
       int m = s.size();
       int n = p.size();

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

       vector<vector<int>> f(m + 1, vector<int>(n + 1));
       f[0][0] = true;
       for (int i = 0; i <= m; ++i) {
    
    
           for (int j = 1; j <= n; ++j) {
    
    
               if (p[j - 1] == '*') {
    
    
                   f[i][j] |= f[i][j - 2];
                   if (matches(i, j - 1)) {
    
    
                       f[i][j] |= f[i - 1][j];
                   }
               }
               else {
    
    
                   if (matches(i, j)) {
    
    
                       f[i][j] |= f[i - 1][j - 1];
                   }
               }
           }
       }
       return f[m][n];
   }
};

4. Análisis de complejidad

  • Complejidad del tiempo: O ( mn ) O(mn)O ( m n ) donde m y n son las longitudes de las cadenas s y p respectivamente. Necesitamos calcular todos los estados, y la complejidad temporal de cada transición de estado esO ( 1 ) O(1)O ( 1 )
  • Complejidad del espacio: O ( mn ) O(mn)O ( m n ) , que es el espacio utilizado para almacenar todos los estados.
    Enlace de referencia: https://leetcode.cn/problems/regular-expression-matching/solution/zheng-ze-biao-da-shi-pi-pei-by-leetcode-solution/

Supongo que te gusta

Origin blog.csdn.net/qq_43679351/article/details/124927301
Recomendado
Clasificación