6. 字符串 - 串存储结构及KMP算法

6. 字符串 - 串存储结构及KMP算法

6.1 字符串基本概念

  • 串结构是用于存储字符类型的数据的线性存储结构
  • 根据串中存储字符的数量及特点,对一些特殊的串进行了命名和分类:
    • 空串:存储 0 个字符的串,例如 S = ""(双引号紧挨着)
    • 空格串:只包含空格字符的串,例如 S = " "(双引号包含 5 个空格);
    • 子串和主串:假设有两个串 a 和 b,如果 a 中可以找到几个连续字符组成的串与 b 完全相同,则称 a 是 b 的主串,b 是 a 的子串,字串又称为模式串。子串在主串中的位置:指的是子串首个字符在主串中的位置。

6.2 串存储结构实现方法

存储一个字符串,数据结构包含以下 3 种具体存储结构:

6.2.1 定长顺序存储

  • 定长顺序存储:实际上就是用普通数组(又称静态数组)存储。
  • 例如 : char str[22] = "Nothing is impossible!";

6.2.3 堆分配存储

  • 堆分配存储 : 其实现方式是采用动态数组来存储字符串
  • 堆区的内存空间需要手动使用 malloc() 函数申请,并且在不用后要手动通过 free() 函数将其释放,该函数库头文件为 #include <stdlib.h>
  • 例如 : char * str = (char*)malloc(5*sizeof(char));

6.2.3 块链存储

  • 串的块链存储 :即使用链表结构存储字符串
  • 例如:
#define linkNum 3          // 全局设置链表中每个节点存储字符的个数
typedef struct Link {
    char a[linkNum];      // 数据域可存放 linkNum 个字符数据
    struct Link * next;  // 代表指针域,指向直接后继元素
}link;  

6.3 串的模式匹配算法

  • 串的模式匹配算法 :是一种用来判断两个串之间是否具有"主串与子串"关系的算法
  • 实现串的模式匹配的算法主要有以下两种:
    • BF算法 :普通的模式匹配算法
    • KMP算法 :快速模式匹配算法

6.3.1 BF算法 - 普通模式匹配算法

  • 普通模式匹配算法,其实现过程没有任何技巧,就是简单粗暴地拿一个串同另一个串中的字符一一比对,得到最终结果
  • 该算法最理想的时间复杂度 O(n),n 表示串 A 的长度,即第一次匹配就成功。最坏情况的时间复杂度为 O(n*m),n 为串 A 的长度,m 为串 B 的长度。
#include <stdio.h>
#include <stdlib.h>
#include<stdint.h>
// 串普通模式匹配算法的实现函数
int BF_Mate(char* leadstr, char* matestr) {
    int i = 0, j = 0;
    int leadstrlen = strlen(leadstr);
    int matestrlen = strlen(matestr);
    while (i < leadstrlen && j < matestrlen) {
        if (leadstr[i] == matestr[j]) {
            i++;
            j++;
        }
        else {  
            i = i - j + 1;
            j = 0;
        }
    }
    // 跳出循环有两种可能 : 
    // (1) i = leadstrlen, 说明已经遍历完主串, 匹配失败;
    // (2) j = matestrlen, 说明子串遍历完成, 在主串中成功匹配
    return j == matestrlen ? (i - j) : 0;
}
int main() {
    char lead[] = "abaabababbababaabaabaababbbababaabaabaaabbaba";
    char mate[] = "abaabaabaaabbaba";
    printf("BF算法匹配结果为 :%d\n", BF_Mate(lead, mate));
    return 0;
}

6.3.2 KMP算法 - 快速模式匹配算法

  • KMP算法难度系数较大,其实现函数如下:
#include <stdio.h>
#include <stdlib.h>
#include<stdint.h>
// Next数组求解
void Next(char* matestr, int* next) {
    next[0] = -1;
    int i = 0;
    int j = -1;
    int matestrlen = strlen(matestr);
    while (i < matestrlen - 1) {
        if (j == -1 || matestr[i] == matestr[j]) {
            i++;
            j++;
            next[i] = j;
        } else {
            j = next[j];
        }
    }
}
int KMP_Mate(char* leadstr, char* matestr) {
    int i = 0, j = 0;
    int leadstrlen = strlen(leadstr);
    int matestrlen = strlen(matestr);
    int *next = (int*)malloc(matestrlen *sizeof(int));
    Next(matestr, next);// 根据模式串, 求解next数组
    printf("next =");
    for (int t = 0; t < matestrlen; t++) {
        printf(" %d", next[t]);
    }
    printf("\n");
    while (i < leadstrlen && j < matestrlen) {
        if (j == -1 || leadstr[i] == matestr[j]) {
            i++;
            j++;
        } else {
            j = next[j];
        }
    }
    return j == matestrlen ? (i - j) : 0;
}
int main() {
    char lead[] = "abaabababbababaabaabaababbbababaabaabaaabbaba";
    char mate[] = "abaabaabaaabbaba";
    printf("KMP算法匹配结果为 :%d\n", KMP_Mate(lead, mate));
    return 0;
}

感谢阅读 若有错误 敬请见谅!!!


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

园长QwQ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值