¿Cuál es el enfoque algorítmico para resolver el problema de hackerrank Substring Diff?

Además de la solución O (N ^ 2) mencionada por Raziman, también podemos tener una solución O (N ^ 2 log N) utilizando la búsqueda binaria.

Para encontrar el valor máximo de L, buscamos binariamente en él. Esto funciona porque si existe para L particular i, j tal que M (i, j, L) <= K, entonces obviamente para todo l <L, también existe i, j tal que M (i, j, l ) <= K.

Entonces tenemos

  int bajo = 0, alto = l, medio;
             while (bajo > 1;
                 if (resolver (medio)) bajo = medio;
                 más alto = medio - 1;
             }

Ahora la función resolver (x) devolverá verdadero si existimos alguna i, j tal que M (i, j, x) <= K. Esto se puede implementar en el tiempo O (N ^ 2) usando algún cálculo previo.
Podemos mantener un recuento de matriz [i] [j] que nos dirá el número de desajustes entre las cadenas [i-min (i, j) … i] y [j-min (i, j) … j]. Usar esto para cualquier i, j, M (i, j, x) se puede calcular como cuenta [i + x-1] [j + x-1]-cuenta [i-1] [j-1].
Por lo tanto, la función resolver (x) se convierte en algo así:

  resolver (int mid) {
        para (int i = mid; i <= l; i ++) {
             para (int j = mid; j <= l; j ++) {
                 int tmp = cuenta [i] [j] - cuenta [i-mid] [j-mid];
                 if (tmp <= K) devuelve verdadero;
             }
         }
         falso retorno;
 }

Finalmente, una programación dinámica simple para calcular el recuento [] [] en O (N ^ 2)

  l = P.length ();
             para (int i = 0; i <l; i ++) {
                 para (int j = 0; j <l; j ++) {
                     cuenta [i + 1] [j + 1] = ((P.charAt (i) == Q.charAt (j))? 0: 1) + cuenta [i] [j];
                 }
             }

Utilice los dos punteros / método de ventana deslizante.

Tenga en cuenta que la solución O (N³) es bastante sencilla. Para cada par (i, j), encuentre el mayor valor de L tal que M (i, j, L) ≤ k. Como hay O (N²) tales pares y necesita operaciones O (N) para calcular el máximo L para cada par (solo necesita una operación para calcular M (i, j, L + 1) cuando tiene M (i, j , L) ya calculado), todo el algoritmo tarda O (N³) en tiempo.

  def getbest (k)
   mejor = 0
   para i = 1 a N
     para j = 1 a N
       malo = 0
       para l = 0 a N
         si i + l> N o j + l> N
           mejor = max (mejor, l)
           descanso
         fin

         si p [i + l]! = q [j + l]
           malo = malo + 1
         fin

         si es malo> k
           mejor = max (mejor, l)
           descanso
         fin
       fin
     fin
   fin

   volver mejor
 fin

Ahora, ¿cómo puede mejorar la complejidad de O (N³) a O (N²)? Suponga que ha encontrado la L más larga que da M (i, j, L) ≤ k para dado (i, j). Supongamos que no nos detuvimos en L porque llegamos al final de la cadena, sino porque los siguientes caracteres no coinciden y tomaron nuestro recuento de discrepancias por encima de k. Esto significa que M (i, j, L) = k y M (i, j, L + 1) = k + 1.

La observación clave ahora es que no necesitamos calcular M (i + 1, j + 1, l) para l M (i + 1, j + 1, L-1) será k o k-1, dependiendo de si p (i) y q (j) son iguales o no. Podemos comenzar con este valor e intentar aumentar l desde L-1 para ver cuánto más alto puede llegar. Como incrementamos el índice del límite izquierdo o derecho del intervalo que estamos viendo en cada paso, el algoritmo toma tiempo O (N) para cada valor de ij. Como solo hay valores 2N-1 de ij, la complejidad general es O (N²).

  # Esta función comienza en (i, j) y usa dos punteros para encontrar el máximo l
 # que da M (i ', j', l) <= k entre todos (i ', j') de modo que i '> = i e i'-j' = ij
 # Así que solo necesitamos usar esto con al menos uno de i, j siendo 1
 def getbest (i, j, k):
   mejor = 0, malo = 0
   i '= i, j' = j, l = 0
   mientras que 1
     si i '+ l> N o j' + l> N
       mejor = max (mejor, l)
       descanso
     fin

     si p [i '+ l]! = q [j' + l]
       malo = malo + 1
     fin

     si es malo> k
       mejor = max (mejor, l)
       mientras que p [i '] == q [j']
         i '= i' + 1, j '= j' + 1, l = l-1
       fin
       malo = malo-1
       i '= i' + 1, j '= j' + 1
     más
       l = l + 1
     fin
   fin

   volver mejor
 fin

 # Aquí está la función que hace el trabajo completo
 def getbest (k)
   mejor = 0
   para i = 1 a N
     best = max (best, getbest (1, i, k), getbest (i, 1, k))
   fin
   volver mejor
 fin

More Interesting

¿Todos los NP-HARD que son decidibles también son NP-Complete?

¿Ha cambiado recientemente el algoritmo de Quora?

¿El uso de algoritmos en una clave de contraseña típica de 256 bits que siempre está cambiando pero que aún se muestra al usuario (como en un teléfono, por ejemplo) para crear código requeriría supercomputadoras más rápidas disponibles para superarlo?

¿Qué libro debo consultar para estructuras de datos en c ++?

¿Hay algún libro que tenga todos los códigos para todas las estructuras de datos? ¿Al menos para todas las estructuras de datos de árbol?

Suponiendo una memoria infinita, ¿siempre es posible aumentar la complejidad de cualquier programa sin introducir redundancia?

¿Qué algoritmo da sugerencias en un corrector ortográfico?

¿Los mismos algoritmos dan resultados diferentes en diferentes paquetes / idiomas?

¿Cuál es el algoritmo euclidiano para encontrar GCD? ¿Es un algoritmo tan bueno en términos de rendimiento y análisis de tiempo de ejecución?

¿Es la estructura de datos y el conocimiento del algoritmo un requisito previo para los problemas en Topcoder?

¿Qué algoritmo está detrás de la convolución en MATLAB?

¿Cómo se puede calcular su edad en días? Necesito el algoritmo más simplificado para resolverlo.

¿Qué estructura de datos es adecuada para almacenar una gran cantidad de cadenas en Java?

¿Qué estructuras de datos admiten la inserción, eliminación y selección de un elemento aleatorio con un límite de complejidad de tiempo O (1) que permite duplicados?

¿Cuál es la diferencia entre un algoritmo genético y el recocido simulado?