algoritmo de coincidencia de cadenas de pequeña nota

Coincidencia Algoritmo

algoritmo de fuerza bruta

BF algoritmo, también conocido como algoritmo simple coincidencia de patrones fue propuesto por Bruce Fuerza para el algoritmo idea básica es simple y burda comparación de un problema. C implementación del algoritmo de código es simple, pero se encontró con algunos problemas en la operación de detalle.
problemas con el código

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define LEN 100

int B_FIndex(char S[],char T[])
{
    int i = 0,j = 0;
    int Len_S = strlen(S); // 使用strlen函数获取字符串长度
    int Len_T = strlen(T);

    if(S == NULL || T == NULL || Len_S < Len_T)     // Error Input
        return -1;

    while(i < Len_S && j < Len_T)
    {
        if(S[i] == T[j])
        {
            i++;
            j++;
        }// end if
        else
        {
            i = i - j +1;
            j = 0;
        }// end else
    }//end while

    if(j >=Len_T)
    {
        printf("Success patterened at %d",i-j);	// 匹配成功位置信息提示
        return 0;
    }
    else
    {
        printf("Fail patterened");
        return -1;
    }
}//end BF

int main(int argc,char * argv[])
{
    char S[LEN+1],T[LEN+1];

    fgets(S,sizeof(S),stdin);	// 采用推荐的安全函数fgets
    fgets(T,sizeof(T),stdin);

    B_FIndex(S,T);
}

Este código primera vista no hay problema, y no hay diferencia en el blog otro código, el compilador se pueden pasar, pero no pueden igualar el 100% correcto, ¿por qué dice?
case1: = subcadena de serie maestro

hello world
hello world
Success patterened at 0
Process returned 0 (0x0)   execution time : 16.536 s
Press any key to continue.

Puede corregir expectativas de producción.
Caso 2: subcadena <cadena principal

hello world
hello
Fail patterened
Process returned 0 (0x0)   execution time : 9.249 s
Press any key to continue.

Esto es lo que hace?
Debido scanf () función sólo puede recibir una cadena continua, entonces el final de los espacios de encuentro, tener un impacto en la función de emparejamiento, así que elegimos el fgets () función (relación () obtiene función es más seguro, universal).
Si cambiamos para dirigir gets () función en una aplicación típica es ningún problema, el código anterior funciona correctamente. Pero gets () Función mayor problema es que no comprueba si la entrada es superior a la longitud de la matriz, lo que provoca desbordamiento de la memoria problemas de seguridad.
La verdadera razón por la que causa el problema en otra diferencia con los fgets () y gets () es:

  • gets () lee los caracteres de uno en uno, leyó el salto de línea guía es parada (descarte nueva línea)
  • fgets () tiene una velocidad en el carácter, hasta que encuentra la primera rotura de línea o han sido leídos en el sizeof (str) -1 caracteres al final de la operación. Si se lee una nueva línea, que se ahorre con saltos de línea y otros caracteres .

Entonces, la pregunta clave es el carácter de nueva línea.
En el caso de la case1, la cadena principal

h mi l l la w la r l re '\norte' '\ 0'

También para cuerdas

h mi l l la w la r l re '\norte' '\ 0'

Por lo que el partido tiene éxito, no hay problema.
Pero en case2, como una cadena

h mi l l la '\norte' '\ 0'

Por lo tanto haciendo que la subcadena coincidente es tomar el tiempo para ir al encuentro de nueva línea.

Cuando el análisis anterior es el problema, la solución es calcular la longitud de la cadena en la línea correcta función de alimentación BF perdido, el código de la llave se modifica como sigue

    int Len_S = strlen(S) - 1; // 使用strlen函数获取字符串长度,不包含结束符,
    int Len_T = strlen(T) - 1; // 减1就去掉了换行符。

Por supuesto, hay otras maneras, sólo para poner enmiendas específicas a plazo a este problema.

algoritmo KMP

Acerca de este algoritmo no está aquí, C ++ código directamente dada
función siguiente
método da aquí dos tipos de función siguiente, el trabajo puede

/* 求模式全的netx[]函数
   next[]下标从0开始,初始值定位-1
   S:cdbcbabcdbcdbcacabc
   T:bcdbcdbca
*/

#include <iostream>
#include <string>

using namespace std;

int get_next1(string T,int next[])
{
    next[0] = -1;
    int k = -1;

    for (int i = 1; i < T.size(); i++)
    {
        while (k > -1 && T[k + 1] != T[i])///如果匹配到某一个不相等的时候,开始回溯
        {
            k = next[k];///回到next数组中记录的位置重新匹配
        }
        if (T[k + 1] == T[i] || k == -1)///如果字符一样,继续向前匹配
        {
            k++;
        }
        next[i] = k;///将最大匹配的值赋给next数组
    }
}

int get_next2(string T,int next[])
{// 求next函数的值,
    int i = 0;
    signed int j = -1;
    next[0] = -1;       // initialization
    while(i < T.size())     // 与T[0]字符的ASCII值比较,显然始终成立
    {
        if(j == -1 || T[i] == T[j])
        {
            ++i;
            ++j;
            next[i] = j;
        }
        else
            j = next[j];
    }
}

int main(int argc,char* argv[])
{

    string T;

    cout << "Please input Substring: ";
    cin >> T;
    int next[T.size()] = {0};
    get_next1(T,next);
    cout << "The next[] of substring T:";
    for(int i =0; i <T.size(); i++)
        cout << next[i] << " ";

    cout << endl;

    get_next2(T,next);
    cout << "The next[] of substring T:";
    for(int i =0; i <T.size(); i++)
        cout << next[i] << " ";

    cout << endl;
}

exportación

Please input Substring: bcdbcdbca
The get_next1 of substring T:-1 0 0 0 1 2 3 4 0
The get_next2 of substring T:-1 0 0 0 1 2 3 4 5

Process returned 0 (0x0)   execution time : 4.611 s
Press any key to continue.

KMP lograr

#include <iostream>
#include <cstring>
using namespace std;


/*
    得到next数组
*/
void get_next(string T, int *next)
{
    int j, k;
    j = 0;
    k = -1;
    next[0] = -1;
    while(j <T.size())
    {
        if(k == -1 || T[j] == T[k])
        {
            j++;
            k++;
            next[j] = k;
        }
        else
        {
            k = next[k];
        }
    }
}

/*
    KMP算法
*/
int KMP(string S, string T, int *next)
{
    int i = 0, j = 0;
    get_next(T, next);
    int Len_S = S.size();
    int Len_T = T.size();

    while (i < Len_S && j < Len_T)
    {
        if (j == -1 || S[i] == T[j])
        {
            i++;
            j++;
        }
        else
        {
            j = next[j];
        }
    }
    if (j == Len_T)
    {
        cout << "Success patterned with shift " << i-j <<endl;
        return i - j;
    }
    else
    {
        cout << "Fail patterned" << endl;
        return -1;
    }
}

int main()
{
    string S,T;
    cin >> S ;
    cin >> T;
    int next[T.size()];
    int i;

    Get_Next(T, next);
    cout << "模式串的next的值为:";
    for (i = 0; i < T.size(); i++)
        cout << next[i] << " ";
    cout << endl;
    KMP(S, T, next);
}

exportación

cdbcbabcdbcdbcacabc
bcdbcdbca
模式串的next的值为:-1 0 0 0 1 2 3 4 5
Success patterned with shift 6

Process returned 0 (0x0)   execution time : 19.706 s
Press any key to continue.
Publicado 25 artículos originales · ganado elogios 23 · Vistas a 10000 +

Supongo que te gusta

Origin blog.csdn.net/Secur17y/article/details/100585369
Recomendado
Clasificación