[数据结构]:19-串KMP模式匹配(数组)(C语言实现)

目录

前言

已完成内容

KMP算法实现

01-开发环境

02-文件布局

03-代码

01-主函数

02-头文件

03-StringCommon.cpp

04-StringFunction.cpp

结语


前言

        此专栏包含408考研数据结构全部内容,除其中使用到C++引用外,全为C语言代码。使用C++引用主要是为了简化指针的使用,避免二重指针的出现。

已完成内容

[数据结构]:01-顺序表(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:02-单链表(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:03-栈(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:04-循环队列(数组)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:05-循环队列(链表)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:06-队列(链表带头结点)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:07-二叉树(无头结点)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:08-顺序查找(顺序表指针实现形式)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:09-二分查找(顺序表指针实现形式)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:10-二叉排序树(无头结点)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:11-冒泡排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:12-快速排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:13-插入排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:14-选择排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:15-堆排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:16-归并排序(顺序表指针实现形式)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:17-双链表(带头结点)(C语言实现)_Chandni.的博客-优快云博客

[数据结构]:18-链栈(不带头结点)(C语言实现)_Chandni.的博客-优快云博客

KMP算法实现

01-开发环境

        语言:C/C++14

        编译器:MinGW64

        集成开发环境:CLion2022.1.3

02-文件布局

        请在CLion集成开发环境中创建C++可执行程序,否则无法运行,原因上面已解释。

                        ​​​          

03-代码

01-主函数

        用于测试KMP算法。

// 0号位置不存元素,使数组下标与字符串位置保持一致
#include "./Head/StringData.h"
#include "./Source/StringCommon.cpp"
#include "./Source/StringFunction.cpp"

int main() {
    SqString String;
    // 初始化
    InitString(String);
    char Str[] = "abascbascabaaba";
    CreateString(String, Str);

    // KMP
    SqString Sub;
    // 初始化
    InitString(Sub);
    char Str1[] = "abaaba";
    CreateString(Sub, Str1);
    int next[Sub.Length + 1];
    GetNext(Sub, next);

//    int nextval[Sub.Length + 1];
//    GetNextval(Sub, nextval);
    // 输出
    for (int i = 1; i <= Sub.Length; i++) {
        printf("%3d", next[i]);
    }
    printf("\n");
    int pos = IndexKMP(String, Sub, next);
    printf("pos = %d\n", pos);
    return 0;
}

02-头文件

        用于存储结构体和常量等。

//
// Created by 24955 on 2023-03-21.
// 0号位置不存元素,使数组下标与字符串位置保持一致
//

#ifndef INC_01_SQSTRING_STRINGDATA_H
#define INC_01_SQSTRING_STRINGDATA_H
// 头文件
#include <stdio.h>
#include <stdlib.h>

// 常量
#define MaxSize 30
typedef char ElemType;

// 结构体-顺序存储
typedef struct {
    ElemType ch[MaxSize];
    int Length;
} SqString;
#endif //INC_01_SQSTRING_STRINGDATA_H

03-StringCommon.cpp

        用于存储串初始化和打印输出等公用函数。

//
// Created by 24955 on 2023-03-21.
// 0号位置不存元素,使数组下标与字符串位置保持一致
//
// 初始化串
void InitString(SqString &String) {
    String.Length = 0;
}

// 创建串
void CreateString(SqString &String, char Str[]) {
    for (int i = 1; Str[i - 1] != '\0'; i++) {
        String.ch[i] = Str[i - 1];
        String.Length++;
    }
}

// 判断字符串是否为空
bool StrEmpty(SqString String) {
    if (String.Length == 0) {
        return true;
    }
    return false;
}

// 串输出
void StringPrint(SqString String) {
    if (StrEmpty(String)) {
        return;
    }
    for (int i = 1; i <= String.Length; i++) {
        printf("%c", String.ch[i]);
    }
    printf("\n");
}

04-StringFunction.cpp

        用于存储串模式匹配等操作。

//
// Created by 24955 on 2023-03-21.
// 0号位置不存元素,使数组下标与字符串位置保持一致
//
// KMP优化-nextval数组
void GetNextval(SqString Sub, int nextval[]) {
    /*
     * 1. 模式串相同元素取消重复匹配
     * 2. next[i] = next[next[j]]*/
    nextval[1] = 0;
    // 0号位置不存元素,使数组下标与字符串位置保持一致
    int i = 1, j = 0;
    while (i <= Sub.Length) {
        if (j == 0 || Sub.ch[i] == Sub.ch[j]) {
            i++;
            j++;
            if (Sub.ch[i] != Sub.ch[j]) {
                nextval[i] = j;
            } else {
                nextval[i] = nextval[j];
            }
        } else {
            j = nextval[j];
        }
    }
}

// next和i、j过程
{/* next
 * 1. 0 1
 * 2. j = next[1]; // 0
 * 3. 0 1 1
 * 4. 0 1 1 2
 * 5. j = next[2]; // 1
 * 6. 0 1 1 2 2
 * 7. 0 1 1 2 2 3
 * 8. 0 1 1 2 2 3 4*/
/* abaaba
 * 1. i = 2;j = 1;
 * 2. i = 2;j = 0;
 * 3. i = 3;j = 1;
 * 4. i = 4;j = 2;
 * 5. i = 4;j = 1;
 * 6. i = 5;j = 2;
 * 7. i = 6;j = 3;
 * 8. i = 7;j = 4;*/}
// 求next数组
void GetNext(SqString Sub, int next[]) {
    next[1] = 0;
    // 0号位置不存元素,使数组下标与字符串位置保持一致
    // Sub.ch[0] = '\0';、Sub.ch[1] = 'a';
    int i = 1, j = 0;
    while (i <= Sub.Length) {
        if (j == 0 || Sub.ch[i] == Sub.ch[j]) {
            i++;
            j++;
            next[i] = j;
        } else {
            j = next[j];
        }
    }
}

// 求子串位置-时间复杂度O(m*n)
int IndexKMP(SqString S, SqString Sub, int next[]) {
    /*
     * 1. i不回溯,j按next值回溯*/
    int i = 1, j = 1;
    while (i <= S.Length && j <= Sub.Length) {
        if (j == 0 || S.ch[i] == Sub.ch[j]) {
            i++;
            j++;
        } else {
            j = next[j];
        }
    }
    if (i <= S.Length + 1) {
        return i - j + 1;
    }
    return 0;
}

结语

        此博客主要用于408考研数据结构C语言实现记录,内有不足,可留言,可讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chandni.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值