Cómo usar el hash rodante y la búsqueda binaria para encontrar la subcadena común más larga

La idea principal para usar la búsqueda binaria en este problema es, si tiene una subcadena común de cierta longitud ‘n’, entonces definitivamente podemos encontrar una subcadena común de longitud menor que ‘n’.

Por lo tanto, encontrar la subcadena común más larga implica los siguientes pasos:

hash1 [] = hash de la cadena 1
hash2 [] = hash de la cadena 2
lo = 0
hi = longitud de la cadena más corta + 1
mid = (lo + hi) / 2
if (subcadena común de longitud == mid):
lo = medio
más
hola = medio

El método ingenuo para encontrar una subcadena común se ejecutará en O (n ^ 2), pero puede hacerlo en O (nlogn). Almacene los hashes de cada subcadena de longitud ‘n’ de una cadena en un conjunto STL, luego calcule el hash para cada subcadena de longitud ‘n’ para la otra cadena y búsquelo en el conjunto. Entonces, la complejidad general de esto será O (n * logn ^ 2).

Puede probar este problema Una historia con cadenas y verificar algunas soluciones ACed si tiene problemas para implementar.

Ya hay algunas buenas respuestas a este hilo. También estoy tratando de dar uno.

Déjenos asumir que usted sabe sobre el hash rodante Si no lo hace, verifique la respuesta de Pawan Bhadauria en este hilo ¿Qué es un hash rodante y cuándo es útil?

Ahora que conoce el hash rodante, podemos comenzar ahora.

Para implementar la búsqueda binaria a cualquier problema, debemos verificar todas las x en S, p (x) => p (y) para todas las y> x.

El punto importante que nos permite usar BS en el problema es que si las cadenas dadas tienen una subcadena común de longitud n, también tienen al menos una subcadena común de cualquier longitud m n.

Entonces, aquí x debe estar en el rango (0, min (| s1 |, | s2 |)) (ambos incluidos). Ahora, para cada x podemos comprobar si existe o no una subcadena común de longitud x. Si existe una subcadena de longitud x, entonces no tenemos que verificar longitudes menores que x o viceversa.

Pseudocódigo para la BS

l = 0, r = min (s1.length (), s2.length ())
mientras que (l <= r) {
mid = l + (rl) / 2
if (p (s1, s2, mid)) // p (s1, s2, len) comprueba la subcadena común
l = medio + 1
más
r = medio – 1
}
volver l-1

Ahora para encontrar es cualquier subcadena común de longitud x existe o no. Para facilitar nuestra salida, tenemos hash rodante.

Para s1, tenemos que encontrar todos los hashes posibles de todas las subcadenas de longitud x y almacenarlos en la tabla hash (he usado stl map para este propósito, puede usar stl set también o cualquier ds de su elección). A continuación, para s2, necesitamos calcular los valores hash de todas las subcadenas de longitud x y comparamos cada valor hash con los valores existentes en la tabla hash si se encuentra una coincidencia, devuelve verdadero. Si no se encuentran coincidencias, se devuelve falso.

Pseudocódigo para Rolling Hash

p (s1, s2, x) {// s1: cadena 1 s2: cadena 2 x: longitud de la subcadena
// Para encontrar hash estoy usando B como primo.
// calcular hash (0) = hash (s1 [0… x-1]) s1 [0] + s1 [1] * B +….
// + s1 [x-1] * pow (B, x-1)
// Para calcular todos los otros hashes, usa esta ecuación
// hash (i) = hash (s1 [i… i + x-1]) = (hash (i-1) – s [i-1]) / B
// + s1 [i + x-1] * pow (B, x-1)
// ahora almacena todos los hashes en la tabla hash
// calcula de manera similar todos los hashes para la cadena 2 y los compara
// con hashes existentes
if (coincidencia encontrada)
volver verdadero
más
falso retorno
}

La complejidad general será log (n) * (nlog (n)).

Gracias Rushal por A2A.

La subcadena común más larga (LCS) de dos cadenas de entrada es una subcadena común (en ambas) de longitud máxima. Podemos relajar las restricciones para generalizar el problema: encontrar una subcadena común de longitud. Entonces podemos usar la búsqueda binaria para encontrar el máximo. Esto lleva tiempo siempre que resolver el problema relajado requiera tiempo lineal.

Encontrar una subcadena común se puede resolver con un hash rodante:

1. Calcular valores hash de todas las subcadenas de longitud de y.
2. Si un hash de coincide con un hash de, entonces hemos encontrado una subcadena común de longitud.

El paso 1 usa un hash rodante para lograr un tiempo lineal y para implementar el paso 2, use una tabla hash. Agregue todos los hashes de las subcadenas de longitud a la tabla. Para cada subcadena de longitud de, búsquela en la tabla. Esto lleva el tiempo lineal esperado para una tabla hash lo suficientemente grande.

Primero observe que la longitud de la subcadena común más larga es como máximo la mínima de las dos cadenas de entrada y que la longitud de la subcadena común más corta es al menos cero (las cadenas no tienen caracteres en común).

izquierda = 0
derecha = min (len (s1), len (s2))
Como tiene un algoritmo para verificar si hay una kcs común de longitud k (llame al algoritmo kcs ). Puede llamarlo O (log n) veces para encontrar el máximo k.

while (izquierda <= derecha) {
k = (izquierda + derecha) / 2
if (kcs (s1, s2, k) == verdadero) {
izquierda = k
}
más {
derecha = k
}
}

More Interesting

¿Cuáles son los mejores recursos para aprender R? Tratando de construir mi propio algoritmo de predicción basado en datos anteriores que tengo en archivos csv y que solía ser un desarrollador de Ruby hace un par de años

¿Cuál es la razón por la cual las compañías gigantes (por ejemplo, Google o Microsoft) hacen preguntas típicas como el árbol de búsqueda binario o el algoritmo tradicional o preguntas como la complejidad del algoritmo? ¿Cuál es el propósito? La mayoría de ellos no se usan en la vida real.

Si está utilizando Java durante las entrevistas algorítmicas, ¿puede omitir las clases de escritura y acceder directamente a los métodos?

Cómo demostrar que el problema del vendedor de viajes es NP-hard

¿Existe algún libro de estructuras de datos y algoritmos en C ++ (tiene código fuente completo en C ++) disponible de forma gratuita en Internet?

¿Cuál es el libro perfecto sobre CPP y algoritmos?

¿Hay algún algoritmo de aprendizaje automático para el que pones una línea y devuelve la línea más cercana en un conjunto de datos?

¿Cuál es la mejor manera de ordenar un terabyte de matriz de datos, cuando tiene RAM limitada (500k), y cada elemento de la matriz tiene un par de elementos de datos, de aproximadamente 1-10k cada uno?

Cómo encontrar diferentes permutaciones de pila

¿Con qué frecuencia los desarrolladores de iOS requieren estructuras de datos y diseño de algoritmos?

En file.log, cada línea comienza con una marca de fecha completa. ¿Qué comando podría usarse para devolverme las líneas N-1, N y N + 1 con una diferencia de tiempo mayor que X segundos entre N y N + 1?

¿Cómo funciona un árbol de expansión y cómo lo configuro?

¿Cómo se debe describir y hablar sobre la recursividad cuando se hace pizarra o se programa un par?

¿Cuál es mi concepto erróneo con respecto al algoritmo de clasificación de fusión aquí?

Cómo resolver la ordenación rápida utilizando un método no recursivo