KMP算法——我欲修仙(功法篇)

简介: KMP算法——我欲修仙(功法篇)


BF算法


BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。BF算法是一种蛮力算法。


1684814442477.png


int BF( char* b,  char* a)
{
  int i = 0, j = 0; 
  int ret = i;//i用来控制主串,j用来控制子串,ret用来记录若有完整的匹配的字符串时,该字符串的起始位置
  //当主串和子串都不为'\0'时,进入循环进行比对
  while (*(b + i) && *(a + j))
  {
  //如果对应元素相同,则都指向下一位
  if (*(b + i) == *(a + j))
  {
    i++;
    j++;
  }
  //不同,则让i回到主串的上一次比较过的元素的第一个元素的后一元素,j赋为0,子串重新比对,
  //ret则等于新的起始位置
  else
  {
    i = i - j + 1;
    j = 0;
    ret = i;
  }
  }
  //若主串对应的元素为0,则代表遍历完成,主串没有与子串相匹配的字符串,
  if (*b == '\0')
  {
  return -1;
  }
  //if如果不执行,下面这个return便会执行。返回下标。
  return ret;
}



显然这种暴力的算法并不高效,于是KMP算法就诞生了。


KMP算法


介绍:


KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)


KMP算法主要分为两部分:1.算法主体 2.获取next[]数组


算法主体


让我们忽略next[]的由来,只是关注算法主体,算法可以写成


int KMP_S(char *a,char *b,int Len_p,int Len_s)
{
  int i = 0, j = 0;
  int* next = build_next(b,Len_s);//获取next[]数组
  while (i < Len_p)
  {
  if (*(a + i) == *(b + j))
  {
    i++;
    j++;
  }//如果两个数相同,这两个数组都向下移动   
  else if (j > 0)
    j = *(next+j-1);//非第一个字符,从跳过next数重新匹配
  else
    i++;//第一个字符匹配时就失配
  if (j == Len_s)
  return i - j;//返回下标值
  }
}


1684814472174.png


next[]数组


next[]数值代表的是在匹配失败的时候字串中可以跳过匹配的字符个数,通过观察我们不难发现,我们跳过的字符与后面的字符完全相同,即前缀和后缀相同,所以我们可以认为next[]数组的本质就是寻找子串中“相同前后缀的长度,并且一定是最长的前后缀”(不包括其本身)

我们可以使用递归的方式去求解next[]数组:


1684814487904.png


int* build_next(int* b, int Len_s)
{
  int i, j = 0;
  int next[MAX] = { 0 };
  for (i = 1;i < Len_s;i++)
  {
  while (j > 0 && *(b + i) != *(b + j))
  {
    j = next[i - 1];
  }
  if (*(b + i) == *(b + j))
  {
    next[i] = j;
  }
  }
  return next;
}



总结:


KMP算法比较难以理解,我发现网上大部分讲解KMP算法的文章都比较难懂事实上在这方面我认为还是通过动画视频的方式可以更加直观的认识到KMP算法的运算方式。

这里我推荐:最浅显易懂的 KMP 算法讲解


#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#define MAX 100
int next[MAX] = { 0 };
/*int* build_next(int* b, int Len_s)
{
  int i, j = 0;
  int next[MAX] = { 0 };
  for (i = 1;i < Len_s;i++)
  {
  while (j > 0 && *(b + i) != *(b + j))
  {
    j = next[i - 1];
  }
  if (*(b + i) == *(b + j))
  {
    next[i] = j;
  }
  }
  return next;
}*/
int* build_next(char* b, int Len_s)
{
  int next[MAX] = { 0 };
  int len = 0, i = 0;
  while (i < Len_s)
  {
  if (*(b + len) == *(b + i))
  {
    len++;
    next[i] = len;
    i++;
  }
  else if (len == 0)
  {
    next[i] = 0;
    i++;
  }
  else
    len = next[len - 1];
  }
  return next;
}//求解next*/
int KMP_S(char *a,char *b,int Len_p,int Len_s)
{
  int i = 0, j = 0;
  int* next = build_next(b,Len_s);
  while (i < Len_p)
  {
  if (*(a + i) == *(b + j))
  {
    i++;
    j++;
  }//匹配成功向下移动   
  else if (j > 0)
    j = *(next+j-1);//非第一个字符,从跳过next数重新匹配
  else
    i++;//第一个字符匹配时就失配
  if (j == Len_s)
    for (;j < i;j++)
    {
    printf("%c", *(a + j));
    return i - j;
    }
  }
}
int main()
{
  char Pst[MAX] = { 0 };
  char Sst[MAX] = { 0 };
  int Len_p = 0;
  int Len_s = 0;
  fgets(Pst, MAX, stdin);
  getchar();
  fgets(Sst, MAX, stdin);
  Len_p = strlen(Pst)-1;
  Len_s = strlen(Sst);
  printf("%d %d\n", Len_p, Len_s);
  KMP_S(Pst, Sst,Len_p,Len_s);
  return 0;
}
目录
相关文章
|
4月前
|
存储 机器学习/深度学习 算法
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty  敏感词
|
3月前
|
机器学习/深度学习 监控 算法
局域网行为监控软件 C# 多线程数据包捕获算法:基于 KMP 模式匹配的内容分析优化方案探索
本文探讨了一种结合KMP算法的多线程数据包捕获与分析方案,用于局域网行为监控。通过C#实现,该系统可高效检测敏感内容、管理URL访问、分析协议及审计日志。实验表明,相较于传统算法,KMP在处理大规模网络流量时效率显著提升。未来可在算法优化、多模式匹配及机器学习等领域进一步研究。
96 0
|
11月前
|
算法
第四章 KMP算法理论基础
第四章 KMP算法理论基础
162 0
|
算法 C++
A : DS串应用–KMP算法
这篇文章提供了KMP算法的C++实现,包括计算模式串的next数组和在主串中查找模式串位置的函数,用于演示KMP算法的基本应用。
|
11月前
|
算法
KMP算法
KMP算法
114 0
|
数据采集 算法 JavaScript
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
JavaScript字符串搜索涵盖`indexOf`、`includes`及KMP算法。`indexOf`返回子字符串位置,`includes`检查是否包含子字符串。KMP是高效的搜索算法,尤其适合长模式匹配。示例展示了如何在数据采集(如网页爬虫)中使用这些方法,结合代理IP进行安全搜索。代码示例中,搜索百度新闻结果并检测是否含有特定字符串。学习这些技术能提升编程效率和性能。
320 1
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
|
算法
KMP算法
KMP算法
96 0
|
算法 Java
KMP算法详解及其在字符串匹配中的应用
KMP算法详解及其在字符串匹配中的应用
|
人工智能 算法 BI
一篇文章讲明白KMP算法(俗称看毛片算法)
一篇文章讲明白KMP算法(俗称看毛片算法)
254 0
|
算法 Java
Java数据结构与算法:字符串匹配算法之KMP算法
Java数据结构与算法:字符串匹配算法之KMP算法

热门文章

最新文章