algoritmo KMP gráfico

Prólogo: En este artículo creo que apunta a abrir ya tenga algún conocimiento del algoritmo KMP, por supuesto, no entendía lo que tenemos que profundizar en lo que hoy es el algoritmo KMP, para que pueda entender este algoritmo funciona con un verdadero sentido de aplicación;

En primer lugar, ¿cuál es el algoritmo KMP

  • KMP algoritmo llamado el (Knuth-Morris-Pratt), es un algoritmo mejorado cadena coincidente, fue propuesto por primera vez por el DEKnuth, JHMorris y VRPratt, su apariencia, sin duda, traer la primavera a la coincidencia de cadenas.
  • De hecho, la esencia del algoritmo KMP está en el proceso de correspondencia, en caso de falta de coincidencia de enlace, no se iniciará inmediatamente la cabeza y de la cadena de coincidencia de patrones, pero la cadena patrón de encordado voluntad de la parte sub-cadena coincidente actual de la población más grande coincide con el principio, es decir, queremos hacer uso de la información ya ha sido igualado, por lo descarte procesos innecesarios, el tiempo mínimo de coincidencia. Carretera es un pequeño discurso claro, o consulte la siguiente explicación.
  • El nacimiento de todos los algoritmos están diseñados para satisfacer nuestras necesidades, KMP no es una excepción, como por ejemplo los siguientes requisitos KMP algoritmo es un escenario clásico:
    Actualmente tengo una cadena str, y otro patrón de encordado (vamos a modo de llamada cadena de ella)
    me gustaría preguntar es si existe un patrón en str, o patrón apareció muchas veces en str;

En segundo lugar, un partido violento

La cara de las demandas eleva por encima ciertamente no entró en contacto con el socio menor del KMP algoritmo también sería primero pensar en este partido violencia algoritmo (BF). ¿Qué es esta idea no es nada más violento partido, define un
i = 0, str apunta al i-ésimo carácter, i es atravesado entonces de 0 a str.length -. Pattern.length de nuevo en el proceso de cada ciclo se define una variable j se representa por puntos en el patrón j-ésimo elemento, los valores de j es 0 a pattern.length, si este ciclo para cada str expresión capa j [i + j] == patrón [j] se ajustan de modo que es una persona compatible, hasta que todo el bucle exterior que atraviesa todo hecho, que no coincide con el éxito, entonces se juzga que no hay un patrón en str.
Mirar el código, que debe ser el método de la gente piensa en primer lugar:

bool BF(string str,string pattern){
    int i=0,j=0;
    while(i < str.length() && j < pattern.length()){
        if(str[i] == pattern[j]){
            i++;
            j++;
        }else{
            i = i-j+1;
            j=0;
        }
    }
    return j == pattern.length();
}

La implementación de este algoritmo se puede utilizar para indicar la siguiente figura:
Aquí Insertar imagen Descripción
Es así de simple y cruda, la ventaja de este algoritmo es simple, no hay riesgo de fuga mal, pero es un inconveniente de la mayoría de los gastos de tiempo mortales son demasiado altos, una miran el análisis de código puede obtener inmediatamente la complejidad de tiempo de O m (m * n), n son la longitud y el patrón de str, str y cuando la longitud del patrón son grandes, el uso de este algoritmo es, sin duda, un desastre, el grandes volúmenes de datos en el poder hoy queremos explorar un algoritmo más elegante y eficiente, que es el héroe de hoy KMP algoritmo.

Tres, el algoritmo KMP

  • Para entender el algoritmo algoritmo KMP, debemos dirigir por primera vez el concepto de una serie de prefijos y sufijos, a qué hora la cadena de prefijo y sufijo, mirada en el siguiente ejemplo creo que inteligente que entiende de inmediato:
    Ejemplo: String = "ABAB"
prefijo sufijo longitud
una si 1
de de 2
aba capítulo 3

Que viste un ejemplo del resultado de la cadena de prefijo y sufijo de un vistazo qué hora, y ahora desea simular lo que la gente está pensando, nuestro cerebro humano al proceso de cómo hacer coincidir las dos cadenas, ver debajo de esta cifra:
Aquí Insertar imagen Descripción
podemos ver por primera vez en el partido a C cuando habíamos fallado para que coincida con el fenómeno, sin embargo, vemos la cadena de prefijo ya ha tenido éxito en el juego aba cadena de patrón no es correcto, entonces vamos a ser capaces de modo prefijo aba movimiento para el emparejamiento aba cadena coincidente, lo que no es cero eliminando la necesidad para el funcionamiento de una pérdida de tiempo, donde se puede ver el núcleo tal es el uso de la información ya ha sido emparejado antes, y luego usarlo para encontrar la mejor opción posición de partida;
podemos mirar para empujar la fórmula isla, P es el primer patrón de cadena de comunidad, la coincidencia de cadenas es T, i T para el índice actual, j es el subíndice actual P:
cuando se produce una falta de coincidencia:

1, sabemos que P [0 a j - 1] == T [i - j a i - 1] Esta expresión se establece que
Aquí Insertar imagen Descripción
puede mirar en la fórmula no entender, pero si le apetece la figura de abajo para limpiar.

2, y luego nos vamos cadena de nuevo este análisis se ha emparejado con éxito (periodo verde) Estructura:
podemos ver que tiene un fenómeno muy extraño:
Aquí Insertar imagen Descripción
es decir, después de la cadena de prefijo sufijo deben tener el mismo lugar aquí introducir el concepto de la cadena pública máxima

cadena prefijo sufijo La longitud máxima del prefijo común y el sufijo
una ^ ^ 0
Automóvil club británico una una 1
aba esto es esto es 2
abcabc a B C a B C 3

Así que ahora podemos obtener una fórmula, sabemos que la porción delantera P ha emparejado con éxito cadena de la cadena es
P [0 a j - 1], si suponemos que la longitud máxima de la común prefijo y sufijo cadena es k, entonces no es una
P [0 a k - 1] == P [j - k para j-1];
Figura:
Aquí Insertar imagen Descripción

3, con los dos primeros expulsados ​​una fórmula podemos ponerlos juntos para ver, habría llegado:

(1) Puesto que P [0 a j - 1] == T [i - j a I - 1]
(2) y desde P [0 a k - 1] == P [j - k -1 a J]
( 3) con (1) (2) hay: T [i - k a i -1] == P [0 a K-1]

Todavía no entiendo puede mirar:
Aquí Insertar imagen Descripción
4, a través de los tres primeros pasos del principio de derivación debe ser llegar a conocer, a continuación, busque la ley, ¿cómo lograr que en un programa de ordenador? Yo no te conozco atrás ahora no es, de hecho, este método es único y diferente de donde empezamos cuando se trata de la ley de violencia es el cambio descalce de enlaces iyj no son la misma;
cómo un método diferente: BF (Violencia) que perdió cuando está equipado con el procesamiento de cero se lleva a cabo a su vez j, i fui de nuevo a la cabeza que han emparejado subcadena.
Y de hecho, cuando KMP algoritmo desajuste aquí, no está j se establece en cero, pero se convirtieron en K, y K es el P [0 a j-1] La longitud máxima de este segmento de la común prefijo y sufijo; si k puede P (patrón de encordado modo) que se requieren todas las posiciones a la cadena no está en línea todavía? Vamos a usar un recipiente siguiente llamada a mantener esta posición para cada valor de k
se puede expresar como K j-ésima posición P (modelo patrón de cadena) siguiente valor de [I];
entonces podemos primero escribir programas que leen:

bool BF(string str,string pattern){
    int i=0,j=0;
    while(i < str.length() && j < pattern.length()){
        if(str[i] == pattern[j]){
            i++;
            j++;
        }else{
        	j = next[j]				// j变next的值,而i不变
        }
    }
    return j == pattern.length();
}

Algunos temen pequeño mareo socio, quiero hacer hincapié en el valor de k no es de la siguiente P [0 a j] este período, y que representa la P [0 a j-1] Este es el mayor sector de la población antes de la longitud del sufijo debe prestar atención! ! !

Bueno, ahora se hace imperativo encontrar matriz siguiente, siempre y cuando la matriz siguiente para encontrar que todo está resuelto.

En cuarto lugar, busque la siguiente matriz

Observando a continuación la primera serie, el primero en descubrir la próxima siguiente ejemplo de la matriz, en la que para encontrar la ley:
Aquí Insertar imagen Descripción
Según nuestro ojo humano puede ver fácilmente el valor en una matriz siguiente, pero para el programa, es necesario el algoritmo, puede ser Analicemos el proceso del cerebro humano para explorar la siguiente matriz de valores, pongo este proceso de buscar la siguiente matriz, un problema de programación dinámica se reduce a, no entienden la programación dinámica tampoco es un problema, a ver el siguiente análisis:
nunca aprendió dinámica de la programación, se que puede ser utilizado cuando el punto de vista de la inducción matemática:
por lo asume: hemos calculado el valor antes de la siguiente matriz de j bits, y junto [j] = k entonces ahora tenemos una matriz:
Aquí Insertar imagen Descripción
ahora nos gustaría pedir j + 1 cómo encontrarlo, ya que todos sabemos que el próximo [j] = k, que representa la cadena (de 0 a j - 1)
la longitud máxima para el público antes del sufijo k, entonces existe la siguiente figura:
Aquí Insertar imagen Descripción
por lo que tratamos de j + 1
el primer paso es calcular esto no es nada más que una cadena de caracteres k + 1 es igual a (j + 1) - 1 carácter puede entenderse de la siguiente manera:
Aquí Insertar imagen Descripción
Si la cadena de k + 1 bits de caracteres igual al bit j entonces no es el carácter siguiente [j + 1] = k + 1 (Esa es la cifra que la longitud de la parte amarilla y verde de la cadena)
en el caso de la igualdad de mejor comprensión, si no igual, cuando, junto [j + 1] ¿cómo debemos buscarlo, no se preocupe estamos hablando de casos de siembra cuando la primera imagen siguientes para leer:
Aquí Insertar imagen Descripción
así, tenemos un diagrama de carta se puede derivar de la siguiente manera:

1. La secuencia de modo conjunto es P, la siguiente matriz tiene su terminación inicialización
2. entonces hay k = nex [j], se puede ver en la figura longitud de la cadena a1 a una longitud de k;
porque el siguiente valor de la matriz P [0 a j - la longitud máxima de la misma como prefijo y el sufijo 1], entonces no A1 (prefijo) = a2 (sufijo);
3. existen k '= siguiente [k], así mismo modo disponible B2 = B1,
4. 2 con 3 puntos y principios como c1 longitud disponible siguiente [k '], y C2 = C1;
5, a continuación, la introducción de la ecuación 2,3,4 punto se puede obtener:.
∵ B1 = B2; C2 = C1 ;
∴ C1 = C2 = C3 = C4;
y A1 = A2 ∵;
∴b1 = B2 = B3 = B4;
∴ C1 = C2 = C3 = C4 = C5 = C6 = C7 = C8;
ordenado para obtener los siguientes resultados :
(. 1) A2 = A1;
(2) = B1 B4;
C1 = C8; (3).
......, ......
(n-) N1 = NN; (hasta P [0, n1] no está tan lejos antes de la sufijo común es decir (al lado [n] = 0 yn = 0))
todavía no desean seguir el siguiente animación se equivoca;
Aquí Insertar imagen Descripción
entonces podemos dibujar un método siguiente gama solicitud preliminar de acuerdo con estas leyes, de la siguiente manera:

vector<int> initNext(string pattern){
    vector<int> next(pattern.length());
    int k;
    next[0] = 0;

    for(int j=0;j<pattern.length()-1;j++){
        k = next[j];
        
        while((k != 0 || next[k] != 0) && pattern[k] != pattern[j]){ // k不能到达0,且两个下标对应的字符不相等时才能循环
            k = next[k];
        }

        if(pattern[k] == pattern[j] && j != k){  // 两个下标指向的字符相等 且 下标不能一样
            next[j+1] = k+1;
        }else{
            next[j+1] = 0;
        }
    }
    return next;
}

Este código está escrito desastre, porque quiero tratar de cumplir con la lógica de nuestro análisis de lo anterior, es un mosaico, pero esta orden debe ser leído a entender mejor el método para encontrar la próxima serie.
Dado que se lee el código, que se deriva del análisis preliminar de las ideas anteriores que seguimos el código, si la manera anterior obviamente está buscando palabras Nexe no son elegantes, que se analiza el código de arriba para hacer algunas simplificaciones:
Primer vistazo a este párrafo:

Aquí Insertar imagen Descripción
Una condición en la que el ciclo anterior es k = 0 || siguiente [k] = 0, lo que es el significado de la misma, no tiene prisa en claro Figura !!:

Aquí Insertar imagen Descripción
Obviamente la figura ha surgido fenómeno falta de coincidencia, pero en este momento de k = 0, y el siguiente [k] la k todavía igual a cero, así que todavía se marcarán un estado, es decir, k ya puntos a la cabeza del patrón, por lo que bien podría ser el siguiente gama 0 -1 con un marcado llegando a su fin, no tiene representantes en frente de ella, el código se puede simplificar a:
Aquí Insertar imagen Descripción
Jaja siendo un desastre, vistazo a esa cifra si se puede simplificar este uno : porque si k == -1 es decir, el otro cuando se activa, entonces el siguiente [j 1] = 0;
esta afirmación no es igual a es próxima [j + 1] = k + 1 ( k se -1 añadir este caso de todos modos tenían un 1 es igual a 0),
entonces se convierte en la siguiente:
Aquí Insertar imagen Descripción
por desgracia o no, aquí hay dos ciclos, ponemos lo comprime en un puesto de trabajo, se encontró que mientras que el bucle interno tiene una muy extraña a saber, que si no tenemos para que coincida, tendrá valor de K iteración sido, pero en el proceso que se j no ha cambiado, entonces ¿por qué no personales para controlar manualmente el valor de j? Aquí Insertar imagen Descripción
Yo sé que es un poco tonto, pero también a los procesos y procedimientos, (donde j- - con el fin de compensar el aumento desde el final de cada parte del ciclo j, j valores con tanta fuerza que no cambia), se puede ver el código anterior que tiene que ser optimizado en un ciclo de,
pero sigue siendo muy bonita, y finalmente a resolver entonces el siguiente código:

vector<int> initNext(string pattern){
    vector<int> next(pattern.length());
    int k=-1,j=0;
    next[0] = -1;

    while(j < pattern.length() - 1){
        if(k == -1 || pattern[k] == pattern[j]){
            next[++j] = ++k;
        }
        else{
            k = next[k];
        }
    }
    return next;
}

Esta es la versión que encantó, de hecho, y esa cifra es para el cambio se convierte en un tiempo, si y otro hecho un trato con un negada (una inversión;

En quinto lugar, el procesamiento final

Después de la explicación anterior, que ya conoce los principios y la solución de la próxima serie de KMP algoritmo, porque el espíritu de excelencia, que los necesita para hacer el procesamiento final, ya que el código anterior hay un error, pero no es fatal, me deja ver a continuación coincidir este caso:
Aquí Insertar imagen Descripción
este caso no es difícil de ver en el mapa, nos falta de coincidencia, patrón de [j] = patrón [ i], en este patrón particular la coincidencia de cadenas a continuación, pertenece claramente a la cadena de AA cuerdas! , que es la primera mitad y la segunda mitad de la misma, que se produce:
cuando un patrón tal situación [siguiente [j]] = patrón [j]:
probar:
! ∵pattern [J] = patrón [i]
k = la Siguiente [J];
la naturaleza de la siguiente disponible: modelo [0: k] == patrón [jk, j]
y el patrón ∵ [K] = patrón [J]
∴ patrón [K] = patrón [I]!

Entonces es claro, es decir, en este caso, estamos haciendo un trabajo útil rollback (k posición de retirada inmediata, pero no pudo igualar el éxito), entonces tenemos que recurrir a un parche en la construcción de la matriz siguiente:

vector<int> initNext(string pattern){
    vector<int> next(pattern.length());
    int k=-1,j=0;
    next[0] = -1;

    while(j < pattern.length() - 1){
        if(k == -1 || pattern[k] == pattern[j]){
            if(pattern[++j] == pattern[++k]){
                next[j] = next[k];
            }else{
                next[j] = k;
            }
        }
        else{
            k = next[k];
        }
    }
    return next;
}

bool serarch(string pattern,string text){
    vector<int> next = initNext(pattern);
    int i=0,j=0;
    const int pLen = pattern.length();
    const int tLen = text.length();

    while((j < pLen) && (i < tLen)){
        if(j == -1 || text[i] == pattern[j]){
            i++;
            j++;
        }
        else{
            j = next[j];
        }
    }
    return j == pLen;
}
  • Conclusión:
    ver KMP algoritmo elimina siguiente configuración de la matriz de tiempo, el tiempo de carga y la precisión de O (n + m), está en contraste marcado con técnicas de violencia, de hecho, entre los miles de algoritmo de coincidencia, sino también una gota en el océano KMP algoritmo, algoritmo no es bueno o malo, correcto e incorrecto únicamente a los puntos, utilizando diferentes algoritmos diferentes escenarios, si usted está interesado en algoritmo de coincidencia de cadenas, el algoritmo podría ir a buscar a domingo, de todos modos, el aprendizaje es un sufrimiento sin fin para el barco que, a aprender mucho, llenándolo en el show!

Hey ~ trama no es fácil, este artículo útil si apunta a dar un paseo elogio canto, hay problemas para ser socios pequeños pueden susurrar o comentario sobre discusión libro de invitados;

Publicado 27 artículos originales · ganado elogios 62 · Vistas a 10000 +

Supongo que te gusta

Origin blog.csdn.net/qq_42359956/article/details/105242127
Recomendado
Clasificación