Algoritmo KMP (notas de estudio)

Resumen del algoritmo KMP (capacitación ACM del Instituto de Tecnología de Nanchang)

(El cerebro duele al pensar en temas estos días)

  • ¿Qué es el algoritmo KMP?

(Voy a citar a alguien más, es muy bueno) El
algoritmo de búsqueda de cadenas de Knuth-Morris-Pratt (conocido como algoritmo KMP, 0.0) puede encontrar la posición de ocurrencia de una palabra W en una cadena de texto principal S.
Este algoritmo evita volver a verificar los caracteres previamente coincidentes al utilizar el hallazgo de que la palabra en sí contiene suficiente información para determinar dónde comenzará la siguiente coincidencia cuando no coincida.

  • ¿Por qué utilizamos el algoritmo KMP?

Primero, introduzcamos el
tema del algoritmo de cadenas de coincidencia ordinarias.
Dada una cadena de patrón S y una cadena de plantilla P, todas las cadenas solo contienen letras en inglés mayúsculas y minúsculas y números arábigos.
La cadena de plantilla P aparece como una subcadena varias veces en la cadena de patrón S.
Calcule el índice inicial de todas las posiciones de la cadena de plantilla P en la cadena de patrón S.

  • Algoritmo ingenuo (violencia)

(Toma prestada la pregunta de la plantilla de y para usarla, jaja)

#include<iostream>

using namespace std;

int main(){
    
    
    string a,b;
    cin>>a>>b;
    for(int i=0;i<a.size()-b.size()+1;i++){
    
    
        string c=a.substr(i,b.size());
        if(c==b) cout<<i<<" ";
    }
}

Pero cuando la longitud de la letra es grande, se agotará el tiempo de espera.
Así nació el algoritmo KMP (jaja, el problema crea el algoritmo)

  • -Solución de algoritmo KMP

Espere un minuto, permítame presentarle cómo usar el algoritmo KMP

  • Principio La
    cadena madre abcdabc
    cadena abc,
    si usamos el algoritmo ingenuo, encontraremos una a una de la cadena madre.
    Pero emparejamos una cuerda muchas veces, lo que fue una pérdida de eficiencia y mejoró mucho el tiempo.
    como

Cadena madre abcdabc
cadena abc cadena
madre abcdabc
cadena * abc
cadena madre abcdabc
cadena ** abc
cadena madre abcdabc
cadena *** abc
cadena madre abcdabc
cadena **** abc

Esta coincidencia es muy repetitiva y los personajes deben coincidir varias veces (triste)

  • El algoritmo kmp implementa el
    algoritmo kmp mediante dos cosas que consisten en la siguiente matriz y la coincidencia de kmp.

  • ¿Cuál es la
    siguiente matriz ? La siguiente matriz almacena principalmente la posición del prefijo y sufijo de la
    subcadena. En la cadena
    p , p [1- j] = p [i-j + 1, i];

  • coincidencia de kmp
    Esta es la coincidencia de subcadenas y cadenas principales. La siguiente matriz se utiliza para evitar la coincidencia repetida de un carácter

  • modelo

//next数组
for (int i = 2, j = 0; i <= m; i ++ )
{
    
    
    while (j && p[i] != p[j + 1]) j = ne[j];
    if (p[i] == p[j + 1]) j ++ ;
    ne[i] = j;
}
// kmp匹配
for (int i = 1, j = 0; i <= n; i ++ )
{
    
    
    while (j && s[i] != p[j + 1]) j = ne[j];
    if (s[i] == p[j + 1]) j ++ ;
    if (j == m)
    {
    
    
    	// 匹配成功后的逻辑
        j = ne[j];
    }
}

¿Crees que es simple? Si lo entiendes, puedes hacer esta pregunta

[Plantilla] Coincidencia de cadenas de KMP

De esta manera, ya tienes un poco de conocimiento para comenzar ~~ (porque el algoritmo KMP está lejos de ser tan simple, jaja) ~~

Ahora debemos aumentar la dificultad para su comprensión del algoritmo KMP

Familiarizado con la siguiente matriz, comprenda esta pregunta

Terminado, parece que ahora tienes un cierto marco

Probemos un CF KMP. Esta
pregunta demuestra completamente el poder de kmp

Esta pregunta explica la siguiente matriz y la coincidencia de kmp más específicamente

Mira mi código de CA (la alegría de CA, jaja)

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int q[]={
    
    1,2,3};
char p[4][N];
int ne[4][N];
int k[4][4];
int len[4];
int ans=0x7fffffff;
void getnext(int m,char p[],int k){
    
    
    for(int i=2,j=0;i<=m;i++){
    
    
        while(j&&p[i]!=p[j+1]) j=ne[k][j];
        if(p[i]==p[j+1]) j++;
        ne[k][i]=j;
    }
}
int kmp(int n,int m,char s[],char p[],int k){
    
    
    int j=0;
    for(int i=1;i<=n;i++){
    
    
        while(j&&s[i]!=p[j+1]) j=ne[k][j];
        if(s[i]==p[j+1]) j++;
        if(j==m) return -1;
    }
    return j;
}
void solve(int i,int j,int l){
    
    
    if(k[i][j]>=0&&k[j][l]>=0) ans=min(ans,len[i]+len[j]+len[l]-k[i][j]-k[j][l]);
    else{
    
    
        if(k[i][j]<0&&k[j][l]<0) ans=min(ans,len[l]);
        else if(k[i][j]<0) ans=min(ans,len[j]+len[l]-k[j][l]);
        else if(k[j][l]<0) ans=min(ans,len[i]+len[l]-k[i][l]);
    }
}
int main(){
    
    
    scanf("%s%s%s",p[1]+1,p[2]+1,p[3]+1);
    for(int i=1;i<=3;i++) len[i]=strlen(p[i]+1);
    for(int i=1;i<=3;i++){
    
    
        getnext(len[i],p[i],i);
        for(int j=1;j<=3;j++){
    
    
            if(i==j) continue;
            k[i][j]=kmp(len[j],len[i],p[j],p[i],i);
        }
    }
    do{
    
    
        solve(q[0],q[1],q[2]);
    }while(next_permutation(q,q+3));
    cout<<ans;
    return 0;
}

Feliz aprendizaje, el algoritmo es un largo camino, estoy muy feliz ~~ (Orz, ven y sálvame) ~~
Pequeño resumen de Mengxin, bienvenidos los grandes para señalar 0.0 me
gusta, soy muy difícil de ver a los niños / (ㄒ o ㄒ) / ~~

Supongo que te gusta

Origin blog.csdn.net/m0_52361859/article/details/112647621
Recomendado
Clasificación