本文代码来自于中国大学MOOC

KMP课件下载

注释内容为自己理解,如有错误请评论,或者私信给我,谢谢

#include <stdio.h>
#include "stdlib.h"
#include "string.h" typedef int Position; Position KMP(char string[25], char pattern[7]); void BuildMatch(char *pattern, int *pInt); #define NotFound -1 int main() {
char string[] = "this is a simple example";
char pattern[] = "simple";
Position p = KMP(string, pattern);
if (p == NotFound) printf("Not found.\n");
else {
printf("%s\n", string + p);
printf("%f\n", p);
}
return 0;
} Position KMP(char *string, char *pattern) {
int n = strlen(string);
int m = strlen(pattern);
int s, p, *match; if (m > n) return NotFound;
match = (int *) malloc(sizeof(int) * m);
// 查询match最长匹配字符串位置值 例如:图1-1
// pattern a b c a b
// index 0 1 2 3 4
// match -1 -1 -1 0 1
BuildMatch(pattern, match); s = p = 0;
while (s < n && p < m) {
if (string[s] == pattern[p]) {
s++;
p++;
} else if (p > 0) {
// 将p置为 前p-1个元素 最大子串长度+1
// 如图1-2
p = match[p - 1] + 1;
} else
s++;
}
return (p == m) ? (s - m) : NotFound;
} void BuildMatch(char *pattern, int *match) {
int i, j;
int m = strlen(pattern);
match[0] = -1;// -1 表示子串长度不存在,无任何相同的元素
for (int j = 1; j < m; ++j) {
// i表示前j-1个元素最大相同子串长度 数组索引位置 index-length 0-1
i = match[j - 1]; while ((i >= 0) && (pattern[i + 1] != pattern[j]))
// 第j个下标的字符和(match[j-1]+1)下标上的元素比较
// 如果不匹配,则根据下标为match[j-1]的相同串基础上进行条件比较
// 因为match[j-1]已经存在,那么绿紫色整块和后面绿紫块肯定一样
// 又第一个小绿块为match[match[j-1]],绿块和紫块相同
// 所以第一个绿块和最后一个紫块相同,只需比较问号位置的值即可
// char[match[match[j-1]]+1] 和 char[j] 的值是否相等
// 如图 1-3
i = match[i]; if (pattern[i + 1] == pattern[j])
// 如图 1-4
match[j] = i + 1;
// 如果都匹配不上就直接设置为-1
else match[j] = -1;
}
}



match[j]的值实际上是前j个(包括j)元素的最大子串长度 对应到数组中的位置 比如图中 j = 6; 最大子串(abca)的长度为4,

在数组中的索引为3



当比较到后面不相等时,模式串相当于要后移到从上往下的第三个横条的情形,也就是把第二个横条情况p = match[p-1]+1

  • 第j个下标的字符和(match[j-1]+1)下标上的元素比较
  • 如果不匹配,则根据下标为match[j-1]的相同串基础上进行条件比较
  • 因为match[j-1]已经存在,那么绿紫色整块和后面绿紫块肯定一样
  • 又第一个小绿块为match[match[j-1]],绿块和紫块相同
  • 所以第一个绿块和最后一个紫块相同,只需比较问号位置的值即可
  • char[match[match[j-1]]+1] 和 char[j] 的值是否相等

KMP(The Knuth-Morris-Pratt Algorithm)的更多相关文章

  1. 字符串匹配算法--KMP字符串搜索(Knuth–Morris–Pratt string-searching)C语言实现与讲解

    一.前言   在计算机科学中,Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串S内查找一个词W的出现位置.此算法通过运用对这个词在不匹配时本身就包含足够的信息 ...

  2. 我所理解的 KMP(Knuth–Morris–Pratt) 算法

    假设要在 haystack 中匹配 needle . 要理解 KMP 先需要理解两个概念 proper prefix 和 proper suffix,由于找到没有合适的翻译,暂时分别称真实前缀 和 真 ...

  3. 笔试算法题(52):简介 - KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm)

    议题:KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm) 分析: KMP算法用于在一个主串中找出特定的字符或者模式串.现在假设主串为长度n的数组T ...

  4. 从时序异常检测(Time series anomaly detection algorithm)算法原理讨论到时序异常检测应用的思考

    1. 主要观点总结 0x1:什么场景下应用时序算法有效 历史数据可以被用来预测未来数据,对于一些周期性或者趋势性较强的时间序列领域问题,时序分解和时序预测算法可以发挥较好的作用,例如: 四季与天气的关 ...

  5. MBMD(MobileNet-based tracking by detection algorithm)作者答疑

    If you fail to install and run this tracker, please email me (zhangyunhua@mail.dlut.edu.cn) Introduc ...

  6. KMP(next数组的更新理解)Codeforces Round #578 (Div. 2)--Compress Words

    题目链接:https://codeforc.es/contest/1200/problem/E 题意: 有n串字符串,让你连起来:sample please ease in out   ---> ...

  7. kmp(前缀出现次数next应用)

    http://acm.hdu.edu.cn/showproblem.php?pid=3336 Count the string Time Limit: 2000/1000 MS (Java/Other ...

  8. kmp(最长前缀与后缀)

    http://acm.hdu.edu.cn/showproblem.php?pid=1358 Period Problem Description For each prefix of a given ...

  9. KMP(超详细复杂度分析)

    从 stackoverflow中找到了一个时间复杂度分析很棒的链接 https://www.inf.hs-flensburg.de/lang/algorithmen/pattern/kmpen.htm ...

  10. kmp(多次无重叠匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=2087 剪花布条 Problem Description 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面 ...

随机推荐

  1. 比Django官方实现更好的分页组件+Bootstrap整合

    前言 Django全家桶自带的分页组件只能说能满足分页这个功能,但是没那么好用就是了 Django的分页效果 django-pure-pagination分页效果 使用方法 首先安装: pip ins ...

  2. Android学习之Layoutinflater的用法

    •她的第一次 话说,那是一个风雪交加的夜晚,看着她独自一个人走在漆黑的小道上,我抓紧跟了过去: 那晚,我们...... 记得第一次接触这个 Layoutinflater 应该是在学习 ListView ...

  3. Android Studio 有关 RecycleView 的使用

    •导入相关包 右击File->Project Structure: 搜索  com.android.support: 找到 recyclerview: 导入好后 Sync Now 同步一下,到这 ...

  4. Redis系列-存储篇sorted set主要操作命令

    Redis系列-存储篇sorted set主要操作函数小结 redis支持有序集合,即sorted set.sorted set在set的基础上,增加了排序属性,是set的升级版.这里简要谈谈sort ...

  5. Java中的泛型 - 细节篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的泛型 - 细节篇>,希望对大家有帮助,谢谢 细心的观众朋友们可能发现了,现在的标题不再是入门篇,而是各种详细篇,细节篇: 是因为之 ...

  6. Android Activity间跳转与传递数据

    1 概述 Activity之间的跳转主要使用 startActivity(Intent intent); startActivityForResult(Intent intent,int reques ...

  7. Go 类型转换与类型判断

    目录 Go 类型转换与类型判断 1.类型转化 2.类型判断 Go 类型转换与类型判断 1.类型转化 T(a) : T 是目标类型 a 是源变量 package main import "fm ...

  8. Salesforce学习之路(一)几个简单概念

    Salesforce是一款非常强大的CRM(Customer Relationship Management)系统,国外企业使用十分频繁,而国内目前仅有几家在使用(当然,国内外企使用的依旧较多),因此 ...

  9. HACK TEH BOX - Under Construction(JWT密钥混淆 + SQL注入)

    HACK TEH BOX - Under Construction(JWT密钥混淆 + SQL注入) 目录 1. JWT密钥混淆 2. 环境 3. Challenge 4. Walkthrough 1 ...

  10. Compound Words UVA - 10391

      You are to find all the two-word compound words in a dictionary. A two-word compound word is a wor ...