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);
}