模式匹配算法

本文介绍了两种模式匹配算法:BF(Brute-Force)算法和KMP算法。BF算法采用蛮力方式逐个比较字符,存在较多回溯。而KMP算法通过next数组避免回溯,提高效率,其时间复杂度为O(m+n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. BF模式匹配算法

算法思想:Brute-Force算法又叫蛮力匹配算法(简称BF算法),从主串S的第pos个字符开始,和模式串T的第一个字符进行比较,若相等,则继续逐个比较后续字符;否则回溯到主串S的第pos+1个字符开始再开始重新和模式串T进行比较,依此类推,直至模式串中的每一个字符依次和主串中的一个连续的字符序列全部相等,则称模式匹配成功,此时返回模式串T的第一个字符在主串S中出现的位置;否则说明主串中没有和模式串相等的字符序列,称模式匹配不成功。

相关代码:

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

#define MAXSIZE 100

int BF(char *s, int pos, char *t);
int BF(char *s, int pos, char *t) {
    int i = pos, j = 0;
    int lens = strlen(s);
    int lent = strlen(t);

    while(i < lens && j < lent) {
        if(s[i] == t[j]) {
            i++;
            j++;
        }else {
            //i-j回到开始匹配的位置,i-j+1去往开始匹配的下一个位置,前提从下标0开始   
            i = i - j + 1;  
            j = 0; 
            printf("回溯到  i: %d\tj : %d\n", i, j); 
        }
    }

    if(j >= lent) {
        return i - lent;
    }else {
        return 0;
    }   
}

void main(void) {
    char S[MAXSIZE] = "ababcabcacbab";
    char T[MAXSIZE] = "abcac";
    int num = BF(S, 0, T);
    printf("%d", num);
} 

以“ababcabcacbab”为主串S,模式串T为“abcac”,则匹配过程如下:

这里写图片描述

从上面的代码的运行结构也可以看出来:
这里写图片描述

2. KMP模式匹配算法

算法思想:Knuth-Morris-Pratt算法(简称KMP),KMP算法是模式匹配的经典算法,与BF算法相比,KMP算法的不同点是消除BF算法中的主串S指针回溯的情况,从而完成串的模式匹配,这样的结果使得算法的时间复杂度为O(m+n),KMP算法每当一趟匹配过程中出现字符比较不等时,主串S中的i指针不需回溯,而是利用已经得到的“部分匹配”的结果将模式向右“滚动”尽可能远的一段距离之后,继续进行比较。

在这个算法中,最关键的点就是需要知道每次在不匹配的时候,模板串应该“滚动的距离”,所以就需要引出next数组了,next[j] = k,next[j]表示当模式中第j个字符与主串中相应字符“失配”时,在模式中需重新和主串中该字符进行比较的字符的位置。

具体代码如下:

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

void kmp(char S[], char T[],int next[]);
void makeNext(char T[],int next[]);

void makeNext(char T[],int next[]) {
    int q,k;
    int m = strlen(T);
    next[0] = 0;

    for (q = 1,k = 0; q < m; ++q) {
        while(k > 0 && T[q] != T[k]) {
           k = next[k-1];           
        }

        if (T[q] == T[k]) {
            k++;
        }
        next[q] = k;
    }
}

void kmp(char S[], char T[],int next[]) {
    int n,m;
    int i,q;

    n = strlen(S);
    m = strlen(T);

    makeNext(T, next);

    for (i = 0,q = 0; i < n; ++i) {
        while(q > 0 && T[q] != S[i]) {
            q = next[q-1];  //p模板           
        }

        if (T[q] == S[i]) {
            q++;
        }
        if (q == m) {
            printf("从下标为 %d 的位置开始匹配.\n",(i-m+1));
        }
    }    
}

void main(void) {
    int i;
    int next[20]={0};
    char S[] = "aaabaaaab";
    char T[] = "aaaab";

    kmp(S,T,next);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值