快速模式匹配算法,简称 KMP 算法。是在BP算法基础上改进得到的。
KMP 算法是一个快速查找匹配串的算法:如何快速在「原字符串」中找到「匹配字符串」。
BF算法的实现过程就是 "傻瓜式" 地用模式串与主串中的字符一一匹配,算法执行效率不高。
一、BP算法代码实现
#include<string>
int BF(string str, string sub) {
// 模式匹配朴素算法
int m = strlen(str.c_str()); // 主串大小
int n = strlen(sub.c_str()); // 子串大小
int i = 0; // 主串索引
int j = 0; // 子串索引
int s = 0; // 主串匹配起始位置
while (i < m && j < n) {
if (str[i] == sub[j]) { // 字符相等
if (j == n - 1) { // 匹配成功
return i - j; // 返回匹配位置
}
i++;
j++;
}
else {
s++; // 开始匹配位置后移1位
i = s; // 主串从s开始
j = 0; // 子串从0开始
}
}
return -1; // 匹配失败
}
二、KMP说明
三、KMP代码实现
C语言
#include<stdio.h>
#include <string.h>
#define MAX_STR_LEN 100
void NextC(const char* T, int* next) {
next[0] = -1;
int n = strlen(T);
int i = 1; // 后缀结束位置
int j = 0; // 前缀结束为止
while (i < n - 1) {
if (j == -1 || T[i] == T[j]) {
i++;
j++;
next[i] = j; // 字符i的next值
}
else {
j = next[j]; // 调整前缀结束位置
}
}
}
int KMPC(const char* S, const char* T) {
int next[MAX_STR_LEN]; //初始化数组
NextC(T, next); //计算next数组
int i = 0; //主串下标索引
int j = 0; //子串下标索引
int m = strlen(S); //主串大小
int n = strlen(T); //子串大小
while (i < m && j < n) {
if (j == -1 || S[i] == T[j]) {
if (j == n - 1) { // 匹配成功
return i - j; // 返回匹配位置
}
i++; j++;
}
else {
j = next[j]; // 子串索引指向next
}
}
return -1; // 匹配失败
}
int main() {
string str = "ababcabcacbab";
string sub = "abcac";
printf("%d\n", KMPC(str.c_str(), sub.c_str()));
return 0;
}
C++
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
vector<int> Next(string sub) {
// sub="AABAAC", next=[-1,0,1,0,1,2]
int n = strlen(sub.c_str()); // 子串大小
vector<int> next(n, -1); // 初始化向量next
int i = 1; // 后缀结束位置
int j = 0; // 前缀结束为止
while (i < n - 1) {
if (j == -1 || sub[i] == sub[j]) {
i++;
j++;
next[i] = j; // 字符i的next值
}
else {
j = next[j]; // 调整前缀结束位置
}
}
return next;
}
int KMP(string str, string sub) {
// KMP算法 str="ababcabcde", sub="abcd", res=5
int m = strlen(str.c_str()); // 主串大小
int n = strlen(sub.c_str()); // 子串大小
int i = 0; // 主串索引
int j = 0; // 子串索引
vector<int> next = Next(sub); // next向量
while (i < m && j < n) {
if (j == -1 || str[i] == sub[j]) { // j=-1表示第一个字符匹配失败
if (j == n - 1) { // 匹配成功
return i - j; // 返回匹配位置
}
i++; j++;
}
else {
j = next[j]; // 指向j的next值
}
}
return -1; // 匹配失败
}
int main() {
cout << "hello world!" << endl;
printf("%d\n", KMP("ababcabcdabcde", "abcd"));
return 0;
}