Ya mencioné un problema difícil que me gusta aquí: la respuesta de Michal Forišek a ¿Cuál es tu problema de programación dinámica favorito?
pero para esta pregunta escogeré otro truco: el truco que fue publicado por primera vez por Dan Hirschberg en 1975.
Este truco se aplicó por primera vez a una clase de problemas de DP relacionados que incluye el cálculo de la distancia Levensthein de dos cadenas, la subsecuencia más larga común de dos secuencias y la alineación óptima de secuencias de ADN. En todos los casos, la instancia son dos objetos de longitud m y n , y el DP se ejecuta en tiempo O (mn) : los estados del DP son todos pares (un prefijo del primer objeto, un prefijo del segundo objeto).
Ya se sabe que la implementación de DP de abajo hacia arriba (iterativa) nos permite ahorrar espacio: el valor de la solución óptima (por ejemplo, la longitud de la subsecuencia común más larga) se puede calcular en tiempo O (mn) mientras solo utilizando O (min (m, n)) espacio: para calcular la siguiente fila de la tabla DP, solo necesitamos recordar una fila anterior. Sin embargo, en realidad , la reconstrucción de una solución óptima parecía requerir tanto O (mn) tiempo y espacio, ya que aparentemente se necesita la tabla completa.
Aquí es donde entra en juego el truco de Hirschberg. Hirschberg ideó una forma inteligente de reconstruir una solución óptima en el mismo tiempo y espacio asintóticos que la solución que solo calculó su valor, es decir, en tiempo O (mn) y O (min (m) n)) espacio.
- ¿Quiénes son algunos de los mejores directores en Kollywood?
- ¿Qué plataformas o herramientas son realmente buenas para hacer que otros revisen tus artículos? ¿Hay algún libre?
- ¿Quién fue el mejor jefe de estado de Corea del Norte?
- ¿Cuál es la mejor manera en que has hecho dinero?
- ¿Cuál es el mejor software para construir un sitio web al estilo de Airbnb?
¿El truco? Usa divide y vencerás para reconstruir la solución. En la primera iteración, encuentre el punto donde la solución óptima cruza la fila central de la tabla DP. Luego, resuelva recursivamente dos problemas más pequeños, cada uno con aproximadamente la mitad de las filas. El punto aquí es que, independientemente de donde la solución óptima cruce la fila del medio, los dos problemas más pequeños juntos tendrán un tamaño aproximadamente igual a la mitad del tamaño del problema original. (Aquí, tamaño del problema = área de la tabla que debemos completar). Por lo tanto, todo el árbol de llamadas y ejecuciones recursivas del algoritmo solo será aproximadamente el doble de lento que el algoritmo original que solo era capaz de calcular el valor.
Para obtener una explicación más detallada y detallada, visite http://www.bioinformaticsonline…. , especialmente la Figura S3.3 que ilustra cómo la construcción de la solución completa se divide en dos subproblemas más pequeños.