【数据结构】串模式匹配算法

95 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情 >>

前言

匹配字串做法有两种,一种是BF算法,另一种是KMP算法。BF算法效率较差,属于轮询比对,KMP算法效率较高。KMP算法又称快速模式匹配算法

BF算法

普通模式匹配算法没有任何技巧,纯粹的就是拿着字串一个一个与主串一一比较筛选出一样的。方法比较简单

  • 假设有 主串ABCADE 字串AD
    • 1.首部位对齐,A与字串AD的A对应,当一样的时候比较子串的第二位与主串是否一致,若一致则进行比较第三位,若不一致则进行第二步
    • 2.将字串向后移动一位,此时A与主串B对齐,此时比较两个是否一致,若不一致再继续后移。

代码实现:

#include <stdio.h>
#include <string.h>
//串普通模式匹配算法的实现函数,其中 B是伪主串,A是伪子串
int mate(char* B, char* A) {
    int i = 0, j = 0;
    while (i < strlen(B) && j < strlen(A)) {
        if (B[i] == A[j]) {
            i++;
            j++;
        }
        else {
            i = i - j + 1;
            j = 0;
        }
    }
    //j=strlen(A),说明子串遍历完成,在主串中成功匹配
    if (j == strlen(A)) {
        return i - strlen(A) + 1;
    }
    //i=strlen(B)说明已经遍历完主串,匹配失败;
    return 0;
}
int main() {
    int number = mate("ababcabcacbab", "abcac");
    printf("%d", number);
    return 0;
}

KMP算法

此算法在BF基础上得到改进,更接近人为判断 比如:

image.png

比较到第四位时发现不相同则下一步会直接从第四步的A进行比较,不会再将A对应B进行比较,因为前三位能匹配成功一定是不相同的。

image.png

第二次匹配直接从第四位开始

由此可知每次匹配失败后,串移动距离不是1而是可能移动多个位置。也可能是1因为当两个相同字符相邻时就是移动1位。

可以使用next数组来提高效率,这个问题我花了很多时间才看懂。 首先需要理解前缀后缀

  • 什么是前缀?出去最后一个字符的字符串就是前缀

    • ex:abc的前缀是ab
  • 什么是后缀?去掉第一个字符的字符串

    • ex:abc的后缀是bc 我们求next数列先将第一位为0,第二位为1,从第三位开始求解前缀与后缀长度相等的值,以此类推就是next的数列。此处有点抽象可以去b站搜个视频看看步骤。