携手创作,共同成长!这是我参与「掘金日新计划 · 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基础上得到改进,更接近人为判断 比如:
比较到第四位时发现不相同则下一步会直接从第四步的A进行比较,不会再将A对应B进行比较,因为前三位能匹配成功一定是不相同的。
第二次匹配直接从第四位开始
由此可知每次匹配失败后,串移动距离不是1而是可能移动多个位置。也可能是1因为当两个相同字符相邻时就是移动1位。
可以使用next数组来提高效率,这个问题我花了很多时间才看懂。 首先需要理解前缀后缀
-
什么是前缀?出去最后一个字符的字符串就是前缀
- ex:abc的前缀是ab
-
什么是后缀?去掉第一个字符的字符串
- ex:abc的后缀是bc 我们求next数列先将第一位为0,第二位为1,从第三位开始求解前缀与后缀长度相等的值,以此类推就是next的数列。此处有点抽象可以去b站搜个视频看看步骤。