Algoritmo KMP (implementación java)

El algoritmo kmp es un método de coincidencia de cadenas mejorado. El núcleo del algoritmo es utilizarDespués de que falla la coincidencia de cadenasdeInformación disponible, Intente reducir los tiempos de coincidencia entre la cadena del patrón y la cadena principal para lograr el propósito de una coincidencia rápida. La implementación específica es a través de una función next (), que a su vez contiene la información de coincidencia local de la cadena de patrón.


∗ * ¿Qué es "falla en la coincidencia de cadenas"?
En primer lugar, primero debemos entender que el mecanismo de coincidencia principal del mecanismo de coincidencia de kmp-kmp está optimizado en el algoritmo BF, luego, ¿qué es el algoritmo BF?
El algoritmo BF (fuerza bruta) es un método de coincidencia de fuerza bruta para cadenas: cada carácter de la cadena principal se compara uno por uno, y el método de coincidencia también se verifica carácter por carácter

 public boolean BF(String query,String target){
    
    
        for(int i=0;i<query.length();i++){
    
    
            int start=i;
            int ptr=0;
            while (ptr < target.length()) {
    
    
                if(query.charAt(start+ptr)!=target.charAt(ptr))
                    break;
                ptr++;
            }
            if(ptr==target.length())
                return true;
        }
        return false;
   }

La falla de coincidencia de cadenas se refiere a la falla en la coincidencia de un carácter de la cadena principal. Por ejemplo, la cadena principal es "abcdcdgadk" y la cadena de patrón es "cdcdk". Cuando coincida con el primer carácter c de la cadena principal:
Inserte la descripción de la imagen aquí




∗ * ¿Cuál es la "información disponible" después de una coincidencia fallida?
La información disponible se refiere a la longitud de la cadena coincidente común del prefijo y sufijo de la cadena patrón (para la cadena patrón "cdc", la longitud del sufijo del prefijo coincidente común es 1 y "cdcd" es 2)


∗ * Entonces, ¿cómo utilizar la información disponible después de que el partido no logre el propósito de reducir el número de partidos?
De manera similar, tome la cadena principal "abcdcdgadk" y la cadena de patrón "cdcdk" en la primera "c" de la cadena principal como ejemplo. Cuando la coincidencia falla, cuando se realiza la siguiente ronda de coincidencia, el prefijo coincidente común de la subcadena de cadena de patrón debe combinarse con Solo cuando los sufijos se superponen, se puede obtener la coincidencia correcta.
Inserte la descripción de la imagen aquí

Con todo, en el algoritmo BF, hay varios caracteres en la cadena de patrón y varios caracteres consecutivos en la cadena principal son todos iguales, pero cuando el último carácter no es igual, la posición de comparación de la cadena principal debe revertirse al final del punto de inicio de la comparación. Una localización. En la situación mencionada anteriormente, el algoritmo KMP no necesita revertir la posición de la cuerda principal, lo que puede mejorar en gran medida la eficiencia.

Al diseñar el algoritmo kmp para resolver el problema, ¿cómo deberíamos implementar la operación del algoritmo kmp? Necesitamos mantener una matriz int next [i] de antemano para almacenar el sufijo de prefijo común de la subcadena antes del carácter i-ésimo en la cadena del patrón. La longitud de la cuerda coincidente.

Ejemplo: para la cadena de patrón "cdcdk"
siguiente [0] = 0, siguiente [1] = 0, siguiente [2] = 1, siguiente [3] = 2, siguiente [4] = 0


Cuando se trata de la siguiente matriz [], podemos utilizar el algoritmo de programación dinámica:

//target是模式字符串(String target)
 int[] next=new int[target.length()];
        for(int i=1;i<target.length();i++){
    
    
           if(target.charAt(i)!=target.charAt(next[i-1]))
               next[i]=target.charAt(i)==target.charAt(0)?1:0;
           else
               next[i]=next[i-1]+1;
        }

Código completo del algoritmo KMP:

public boolean kmp(String query,String target){
    
    
        int longLen=query.length();
        int shortLen=target.length();
        //处理next数组,记录模式串所有字串的公共前后可匹配字符串长度
        int[] next=new int[shortLen];
        for(int i=1;i<shortLen;i++){
    
    
           if(target.charAt(i)!=target.charAt(next[i-1]))
                next[i]=target.charAt(i)==target.charAt(0)?1:0;
           else
               next[i]=next[i-1]+1;

        }
        //match是当前模式字符串在主串中被匹配到的字符的index
        int match=0;
        for(int i=0;i<longLen;i++){
    
    
            if(query.charAt(i)==target.charAt(match))
                match++;
            else{
    
    
                /*
                 *如果match==0时,依然无法匹配,
                 *则无需重新匹配主串当前字符,自动前移,
                 *否则会出现越界问题以及死循环问题
                 */
                if(match!=0) {
    
    
                    /*
                    * 依据已被成功匹配的模式字串的公共前后缀可匹配字符串的长度,
                    * 减少无用的匹配(index在next[match-1]之前的字符已经
                    * 可以成功匹配了)
                    */
                    match = next[match - 1];
                    //i--是为了主串的当前字符重新匹配
                    i--;
                }
            }
            /*
             *如果match的值超过了模式字符串的最大index,
             *则说明模式串被匹配完了,返回true
             */
            if(match==shortLen)
                return true;
     }
        return false;

   }

Supongo que te gusta

Origin blog.csdn.net/CY2333333/article/details/108203076
Recomendado
Clasificación