Informe experimental 4 de "Estructura de datos": coincidencia de patrones de cadenas (algoritmo BF, algoritmo KMP)

1. Propósito del experimento

1. Comprender el concepto básico de cadenas .

2. Dominar la implementación del algoritmo de coincidencia de patrones para cadenas .

2. Vista previa del experimento

Explique los siguientes conceptos

1. Coincidencia de patrones:

        La coincidencia de patrones de cadenas es la operación de posicionamiento de subcadenas .

        Hay dos cadenas S y T, S es la cadena principal (cadena de texto) y T es la subcadena (cadena de patrón) . Encuentre la subcadena que coincida con la cadena de patrón T en la cadena principal S, si la coincidencia es exitosa, determine la posición del primer carácter en la subcadena coincidente en la cadena principal S.

2. Algoritmo BF:

        Brute Force es uno de los algoritmos de coincidencia de patrones.

        Idea de algoritmo: comience a comparar el primer carácter de la cadena principal y la cadena de patrón, y compare el siguiente carácter ;si la coincidencia es exitosa y las comparaciones de caracteres continúan.

3. Algoritmo KMP:

        El algoritmo KMP también es un tipo de algoritmo de coincidencia de patrones, que es un algoritmo de coincidencia mejorado .

        La mejora del algoritmo KMP es que cuando hay una discrepancia de caracteres, no es necesario retroceder los caracteres de la comparación de la cadena principal , mientras que la cadena patrón utiliza la parte de los caracteres que se han emparejado correctamente para determinar la posición de retroceso de la cadena de patrón (no es necesario volver al primer carácter) .

        El algoritmo KMP reduce el número de coincidencias entre la cadena del patrón y la cadena principal para lograr el propósito de una coincidencia rápida .

3. Contenido y requisitos experimentales

 ! Nota !

        Los datos de la matriz de caracteres en este experimento almacenan cadenas a partir del componente de la matriz cuyo subíndice es 0. En algunos libros de texto, para facilitar la explicación del problema, la cadena se almacena desde el componente de la matriz con el subíndice 1 y el componente con el subíndice 0 no se usa, por lo que el código es ligeramente diferente.

1. Lea y ejecute el siguiente programa y escriba el resultado de la ejecución de acuerdo con la entrada.

#include<stdio.h>
#include<string.h>
#define MAXSIZE 100  //串的最大长度

typedef struct{
	char data[MAXSIZE];  //存储串的一维数组(从下标为0的数组分量开始存储字符串)
	int length;          //串的当前长度
}SqString;

int strCompare(SqString *s1,SqString *s2);  /*串的比较*/
void show_strCompare();
void strSub(SqString *s,int start,int sublen,SqString *sub);  /*求子串*/
void show_subString();

int strCompare(SqString *s1,SqString *s2){
	int i;
	for(i=0;i<s1->length && i<s2->length;i++)
		if(s1->data[i] != s2->data[i])
			return s1->data[i] - s2->data[i];
    //字符比较完成,还需比较字符串长度
	return s1->length - s2->length;
	/* s1=s2,返回值=0
	   s1>s2,返回值>0
       s1<s2,返回值<0 */
}

void show_strCompare(){
    SqString s1,s2;
    int k;
    printf("\n***show Compare***\n");
    printf("input string s1:");
    gets(s1.data);
    s1.length=strlen(s1.data);
    printf("input string s2:");
    gets(s2.data);
    s2.length=strlen(s2.data);
    if((k=strCompare(&s1,&s2))==0)
        printf("s1=s2\n");
    else if(k<0)
        printf("s1<s2\n");
    else
        printf("s1>s2\n");
    printf("\n***show over***\n");
}

void strSub(SqString *s,int start,int sublen,SqString *sub){
	int i;
	if(start<1 || start>s->length || sublen>s->length-start+1)
		sub->length = 0;
    else
    {
        for(i=0;i<sublen;i++)
		sub->data[i]=s->data[start+i-1];
	    sub->length=sublen;
    }
}

void show_subString(){
    SqString s,sub;
    int start,sublen,i;
    printf("\n***show subString***\n");
    printf("input string s:");
    gets(s.data);
    s.length=strlen(s.data);
    printf("input start:");
    scanf("%d",&start);
    printf("input sublen:");
    scanf("%d",&sublen);
    strSub(&s,start,sublen,&sub);
    if(sub.length==0)
        printf("ERROR!\n");
    else{
        printf("subString is:");
        for(i=0;i<sublen;i++)
            printf("%c",sub.data[i]);
    }
    printf("\n***show over***\n");
}

int main(){
    int n;
    do{
        printf("\n---String---\n");
        printf("1. strCompare\n");
        printf("2. subString\n");
        printf("0. EXIT\n");
        printf("\ninput choice:");
        scanf("%d",&n);
        getchar();
        switch(n){
            case 1:
                show_strCompare();
                break;
            case 2:
                show_subString();
                break;
            default:
                n=0;
                break;
        }
    }while(n);
    return 0;
}

ingresar:

1

alumno

estudiantes

2

Estructuras de datos informáticos

10

4

resultado de la operación:

2. Implemente el algoritmo de coincidencia de patrones para cadenas. Complemente el siguiente programa para realizar los algoritmos de cadenas BF y KMP.

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

#define MAXSIZE 100  //串的最大长度

typedef struct{
	char data[MAXSIZE];  //存储串的一维数组(从下标为0的数组分量开始存储字符串)
	int length;          //串的当前长度
}SqString;

int index_bf(SqString *s,SqString *t,int start);              /*模式匹配-BF算法*/
void getNext(SqString *t,int next[]);                         /*计算目标串的next数组*/
int index_kmp(SqString *s,SqString *t,int start,int next[]);  /*模式匹配-KMP算法*/
void show_index();

int index_bf(SqString *s,SqString *t,int start){
    //补充代码 
}

void getNext(SqString *t,int next[]){  /*计算模式串t的next数组*/
	int i=0;
	int j=-1;
	next[0]=-1;
	while(i < t->length){
		if(-1==j || (t->data[i]==t->data[j]))
		{
			i++;
			j++;
			next[i]=j;
		}
		else
            j=next[j];
	}
}

int index_kmp(SqString *s,SqString *t,int start,int next[]){
    //补充代码
}

void show_index(){
	SqString s,t;
	int k;
	int i;
	int next[MAXSIZE]={0};
	int nextval[MAXSIZE]={0};
	printf("\n***show index***\n");
	printf("input string s:");
	gets(s.data);
	s.length=strlen(s.data);
	printf("input string t:");
	gets(t.data);
	t.length=strlen(t.data);
	printf("input start position(1≤start position≤%d):",s.length);
	scanf("%d",&k);
	printf("BF:\nthe result of BF is %d\n",index_bf(&s,&t,k));
	getNext(&t,next);
	printf("KMP:\n");
	printf("next[]:");
	for(i=0;i<t.length;i++)
	    printf("%3d",next[i]);
	printf("\n");
	printf("the result of KMP is %d\n",index_kmp(&s,&t,k,next));
	printf("\n***show over***\n");
}

int main(){
	show_index();
	return 0;
}

código de algoritmo BF:

int index_bf(SqString *s,SqString *t,int start){  /*返回模式串t在主串s中第start个字符开始第一次出现的位置;若不存在,返回0*/
    //模式串t长度为0 或 起始查找位置超出主串范围:直接返回0
    if(0 == t->length || start < 1 || start > s->length)
        return (0);
    int pos=start-1;  //pos记录主串s开始匹配的字符下标
    int i=pos;        //i指向主串s当前正待比较的字符下标
    int j=0;          //j指向模式串t当前正待比较的字符下标
    while( i < s->length && j < t->length )
    {
        if(s->data[i] == t->data[j])  //匹配成功:i,j都++,继续比较后续字符
        {
            i++;
            j++;
        }
        else  //匹配失败
        {
            pos++;  //主串开始匹配的位置+1
            i=pos;  //i回溯到主串初始位置下一字符
            j=0;    //j回溯到模式串第一个字符
        }
    }
    if(j >= t->length)
        return (pos-start+2);  //返回模式串t在主串s中第start个字符开始第一次出现的位置
    else
        return (-1);  //查找失败,返回-1
}/*index_bf*/

Código del algoritmo KMP:

int index_kmp(SqString *s,SqString *t,int start,int next[]){  /*返回模式串t在主串s中第start个字符开始第一次出现的位置;若不存在,返回0*/
    //模式串t长度为0 或 起始位置超出主串范围:直接返回0
    if(0 == t->length || start < 1 || start > s->length)
        return (0);
    int i=start-1;  //i指向主串s当前正待比较的字符下标
    int j=0;        //j指向模式串t当前正待比较的字符下标
    while(i<s->length && j<t->length)
    {
        if(-1 == j || (s->data[i] == t->data[j]))
        {
            i++;
            j++;
        }
        else  //匹配失败
        {
            j=next[j];  //i不回溯,j回溯到next[j]
        }
    }
    if(j>=t->length)
        return (i-j-start+2);  //返回模式串t在主串s中第start个字符开始第一次出现的位置
    else
        return (-1);  //查找失败,返回-1
}/*index_kmp*/

ingresar:

abaabb abaa abaa

abaaba

1

resultado de la operación:

3. Sobre la base de la segunda pregunta, mejore la siguiente matriz, realice el algoritmo de cálculo de la matriz nextval de la cadena de destino y verifíquelo.

Código de algoritmo de matriz Nextval:

void getNextVAL(SqString *t,int nextval[]){  /*计算模式串t的nextval数组*/
	int i=0;
	int j=-1;
	nextval[0]=-1;
	while(i < t->length){
		if(-1 == j || (t->data[i]==t->data[j]))
		{
			i++;
			j++;
			if(t->data[i] != t->data[j])
                nextval[i]=j;
            else
                nextval[i]=nextval[j];
		}
		else
            j=nextval[j];
	}
}/*getNextVAL*/

código suplementario de la función show_index:

void show_index(){
	SqString s,t;
	int k;
	int i;
	int next[MAXSIZE]={0};
	int nextval[MAXSIZE]={0};
	printf("\n***show index***\n");
	printf("input string s:");
	gets(s.data);
	s.length=strlen(s.data);
	printf("input string t:");
	gets(t.data);
	t.length=strlen(t.data);
	printf("input start position(1≤start position≤%d):",s.length);
	scanf("%d",&k);
	printf("BF:\nthe result of BF is %d\n",index_bf(&s,&t,k));
	getNext(&t,next);
    getNextVAL(&t,nextval);
	printf("KMP:\n");
	printf("   next[]:");
	for(i=0;i<t.length;i++)
	    printf("%3d",next[i]);
	printf("\n");
    printf("nextval[]:");
	for(i=0;i<t.length;i++)
	    printf("%3d",nextval[i]);
	printf("\n");
	printf("the result of KMP is %d\n",index_kmp(&s,&t,k,nextval));
	printf("\n***show over***\n");
}

ingresar:

abaabb abaa abaa

abaaba

1

resultado de la operación:

Supongo que te gusta

Origin blog.csdn.net/Amentos/article/details/127277450
Recomendado
Clasificación