Un k-palíndromo es una cadena que se transforma en un palíndromo al eliminar como máximo k caracteres de él. Dada una cadena S y un número entero K, ¿encuentra si S es un k-palíndromo o no? Restricciones: S tiene como máximo 20,000 caracteres y 0 <= k <= 30

Se puede resolver en o (n * k * k) programación dinámica.

Considere el algoritmo o (n * n) dado en la descripción.
¿Realmente necesitamos endPointer?
podemos calcular endPointer si conocemos startPointer, número de letras omitidas antes de startPointer y número de letras patrón después de startPointer.

DP [startPtr] [leftRemoved] [rightRemoved] representa el estado con startPointer en startPtr, después de omitir los caracteres leftRemoved a la izquierda de startPointer y rightRemoved chars a la derecha o startPointer.

DP [0] [0] [0] es el caso base.
Lea los comentarios en el código para más detalles.

  cuerda s;  // Cadena de entrada
 int k;  // Entrada k
 char dp [21000] [31] [31];  // Establecer a -1 inicialmente

 char solve (int startPointer, int leftRemoved, int rightRemoved) {
     int endPointer = s.ln - rightRemoved - (startPointer - leftRemoved) - 1;

     if (startPointer> = endPointer) devuelve verdadero;  //Caso base

     char & ret = dp [puntero de inicio] [leftRemoved] [rightRemoved];
     if (ret! = -1) devuelve ret;

     ret = falso;
     // Caso donde los extremos son iguales
     if (s [startPointer] == s [endPointer]) ret = solve (startPointer + 1, leftRemoved, rightRemoved);
     // Comprueba si puedes eliminar un elemento más.
     // En caso afirmativo, verifique después de quitar de adelante y atrás
     if (leftRemoved + rightRemoved <k) {
         ret | = resolver (startPointer + 1, leftRemoved + 1, rightRemoved) ||  resolver (startPointer, leftRemoved, rightRemoved + 1);
     }
     volver ret;
 }

Suraj explica la misma idea que mencioné en mi respuesta en CareerCup – Facebook Interview Question for Interns

La pregunta pregunta si podemos transformar la cadena S dada en su eliminación inversa en la mayoría de las letras K.

Podríamos modificar el algoritmo tradicional de Editar-Distancia, considerando solo las eliminaciones, y verificar si esta distancia de edición es <= K. Sin embargo, hay un problema. S puede tener una longitud = 20,000 y el algoritmo Editar-Distancia toma O (N ^ 2). Lo cual es muy lento.

(De aquí en adelante, supondré que está familiarizado con el algoritmo Editar-Distancia y su matriz DP)

Sin embargo, podemos aprovechar K. Solo estamos interesados ​​* si * logramos eliminar las letras K. Esto significa que cualquier posición a más de K posiciones de distancia de la diagonal principal es inútil porque su distancia de edición debe exceder esas K eliminaciones.

Como estamos comparando la cadena con su reverso, haremos como máximo K eliminaciones e inserciones K (para que sean iguales). Por lo tanto, debemos verificar si ModifiedEditDistance es <= 2 * K

Aquí está el código:

  int ModifiedEditDistance (const string & a, const string & b, int k) {
   int i, j, n = a.size ();
   // muestra por simplicidad.  deberíamos usar solo una ventana de tamaño 
   // 2 * k + 1 o dp [2] [MAX] y filas alternativas.  solo necesita la fila i-1
   int dp [MAX] [MAX];
   memset (dp, 0x3f, tamaño de dp);  // init a un valor> 1.000.000.000
   para (i = 0; i 

Solo procesamos 2 * K + 1 columnas por fila. Entonces este algoritmo funciona en O (N * K), que es lo suficientemente rápido.

Se puede hacer O (n * k) complejidad de tiempo. Básicamente, necesitamos encontrar si la cadena S se puede convertir a su reversa dentro de 2 * k de inserción y eliminación.

Dejame explicarte con un ejemplo. Digamos que la cadena (S) es aabca. Entonces reverso (S ‘) es acbaa. Después de casi la eliminación de k, queremos que la cadena sea un palíndromo, es decir, se lea igual en dirección hacia atrás, es decir, hacia atrás. Podemos tratar esto como un problema de distancia de edición donde solo se permite la eliminación e inserción.

aabca -> (eliminar) abca -> (insertar) acbca -> (eliminar) acba -> (insertar) acbaa

Tenga en cuenta que, eliminar un carácter de la cadena S en realidad se traduce en dos operaciones aquí. Por lo tanto, tenemos que averiguar si S se puede convertir a S ‘con una eliminación de inserción de 2 * k.

Como solo se permite la eliminación de k, al comparar el carácter de S y S ‘, no necesitamos mirar más allá del carácter k (tanto hacia atrás como hacia adelante). Esto se puede hacer en O (n * k) complejidad de tiempo. La complejidad espacial es O (k).

More Interesting

Cómo realizar un recorrido de orden posterior en un árbol binario

¿Debo comenzar a aprender estructuras de datos y algoritmos en lugar de nuevos lenguajes de programación?

Se le da una matriz de números MxN, con la propiedad de que los números aumentan a medida que avanza por cada columna y hacia la derecha en cada fila. ¿Cómo puede verificar eficientemente si un número dado está en la matriz?

¿Cómo se podrían analizar las publicaciones arbitrarias de Reddit para adivinar si el póster es suicida?

¿Qué 'palabras' debo saber para resolver problemas de programación o problemas matemáticos relacionados?

¿Dónde y cómo puedo aprender sobre la creación / comprensión de algoritmos de negociación de acciones?

¿Cuál es la complejidad del tiempo de un algoritmo?

¿Es necesario pensar en una solución recursiva primero antes de proceder a resolver un problema de DP?

¿Por qué Google dice que 'Global University' es una de las mejores universidades?

He estado tratando de aprender el análisis de algoritmos usando el libro CLRS, sin embargo, encuentro que ese libro es difícil de entender. ¿Soy el único?

C: ¿Existe un enfoque general para convertir una función recursiva en iterativa y viceversa?

¿Qué técnicas se utilizan para calcular las probabilidades de caída de elementos en los juegos?

Cómo elegir un elemento único de una lista dentro de un bucle en R

Cómo encontrar la Kth ruta más corta de un nodo a otro en un gráfico

¿Cuál es el mecanismo fundamental detrás de los generadores de números aleatorios?