数据结构- KMP

数据结构 - KMP

引言 & 介绍

  • 由于李总说过串这一章只讲一个KMP, 所以我这里也就只说一个KMP算法了
  • KMP算法, 说得简单点就是关键字搜索

一般方法

  • 一般的关键字搜索的算法为:
 1 int Search(string a, string b) {
 2     int lena = a.length();
 3     int lenb = b.length();
 4     int i = 0, j = 0;
 5
 6     while (i < lena && j < lenb) {
 7         if (a[i] == b[j]) {
 8             i++; j++;
 9         } else {
10             i = i - j + 1;
11             j = 0;
12         }
13     }
14     return j == lenb ? i - j + 1 : -1;
15 }
  • 这个方法的时间复杂度为O(lena * lenb), 可以说是相当高了, 我们可能觉得无所谓, 但是大牛们就会想一种新的算法来优化, 这就是KMP算法, KMP算法的时间复杂度为O(lena + lenb)

KMP算法

KMP函数

  • 如果主串a为“abcdabceabcdabcd”, 模式串b为“abcdabcd”, 一般方法在j = 7(从0开始)时就失配了, 但是, 一般方法就会执行很多无意义的部分, 现在, 我们把代码做一点修改:
int KMP(string a, string b) {
    int lena = a.length(), lenb = b.length();
    int i = 0, j = 0;
    int *next = GetNext(b);

    while (i < lena && j < lenb) {
        if (j == -1 || a[i] == b[j]) {
            i++;    j++;
        } else {
            j = next[j];
        }
    }
    return j == lenb ? i - j + 1 : -1;
}

求next数组

  • 这个代码, 当然是不完整的, 所以这个先看下面这个求next数组的代码:
 1 int* GetNext(string b) {
 2     int j = 0, k = -1;
 3     int len = b.length();
 4     int *next = new int[len + 1];
 5     next[0] = -1;
 6
 7     while (j < len) {
 8         if (k == -1 || b[j] == b[k]) {
 9             j++;
10             k++;
11             next[j] = k;
12         } else {
13             k = next[k];
14         }
15     }
16     return next;
17 }

分析next数组

  • 分析next数组前, 我们再说说主串a为“abcdabceabcdabcd”, 模式串b为“abcdabcd”的情况
  • 当j = 7的时候a[7] 和 b[7]不匹配, 但是a[0 - 6]和b[0 - 6]是匹配的, 如果b[0 - 6]中的前x个字符和后x个字符一模一样, 那么, 我们就无需把j置零, 只需要把j置为x, 直接比较b[x]和a[7]就可以了
  • 而事实上, b[0 - 2]和b[4 - 6]是一样的, 这个x为3, 也可以直接看出, a[4 - 6]和b[0 - 2]是匹配的, 所以我们直接看a[7]和ab[3], 当然啦, 这里a[7] = e, b[3] = d也不匹配, 所以再执行这个步骤·······
  • 上面的x就是next[j], 在GetNext函数里面则是next[k]
  • 现在应该知道next数组的作用了吧, next[j]表示, 在a[i]与b[j]不匹配时, b的前next[j]个字符, 和后next[j]个字符完全相同
  • 知道了next数组的含义之后, 再看上面的函数应该就比较好理解了

GetNext的优化

  • 现在考虑a = “aaabaaabaaab”, b = “aaaa”的情况
  • next数组为{-1, 0, 1, 2, 3}, 这就意味着, j = 3时失配时, j会从3减到-1, 而不是直接从3跳到-1, 如此完美的算法在这一步出了这种情况岂不可惜, 所以, 这个算法还有最后一步优化
 1 int* GetNext(string b) {
 2     int j = 0, k = -1;
 3     int len = b.length();
 4     int *next = new int[len + 1];
 5     next[0] = -1;
 6
 7     while (j < len) {
 8         if (k == -1 || b[j] == b[k]) {
 9             if (b[++j] == b[++k]) {
10                 next[j] = next[k];
11             } else {
12                 next[j] = k;
13             }
14         } else {
15             k = next[k];
16         }
17     }
18     return next;
19 }
  • 将GetNext略作修改就好了

代码

  • 下面给出完整的KMP算法的代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3
 4 int* GetNext(string b) {
 5     int j = 0, k = -1;
 6     int len = b.length();
 7     int *next = new int[len + 1];
 8     next[0] = -1;
 9
10     while (j < len) {
11         if (k == -1 || b[j] == b[k]) {
12             if (b[++j] == b[++k]) {
13                 next[j] = next[k];
14             } else {
15                 next[j] = k;
16             }
17         } else {
18             k = next[k];
19         }
20     }
21     return next;
22 }
23
24 int KMP(string a, string b) {
25     int lena = a.length(), lenb = b.length();
26     int i = 0, j = 0;
27     int *next = GetNext(b);
28
29     while (i < lena && j < lenb) {
30         if (j == -1 || a[i] == b[j]) {
31             i++;    j++;
32         } else {
33             j = next[j];
34         }
35     }
36     return j == lenb ? i - j + 1 : -1;
37 }
38
39 int main () {
40     string a, b;
41     while (cin >> a >> b) {
42         cout << KMP(a, b) << endl;
43     }
44     return 0;
45 }

原文地址:https://www.cnblogs.com/123zhh-helloworld/p/10080842.html

时间: 2024-10-13 16:07:06

数据结构- KMP的相关文章

数据结构--KMP算法总结

数据结构—KMP KMP算法用于解决两个字符串匹配的问题,但更多的时候用到的是next数组的含义,用到next数组的时候,大多是题目跟前后缀有关的 . 首先介绍KMP算法:(假定next数组已经学会,后边next数组会在介绍) 上图T为主链,P为模板链,要求P在T中是否出现,出现就返回位置. 朴素算法会顺序遍历,比较第一次的时候p[0]处失配,然后向后移动继续匹配.数据量大的时候这么做肯定是不可行的.所以这里就会有KMP算法!在一次失配之后,KMP算法认为这里已经失配了,就不能在比较一遍了,而是

数据结构--KMP模式匹配算法

今天,在看数据结构--串这一章节时,看到了KMP算法,相对较复杂些,在此单独做下整理. kmp算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特--莫里斯--普拉特操作(简称KMP算法).KMP算法的关键是根据给定的模式串W1,m,定义一个next函数.next函数包含了模式串本身局部匹配的信息. 例子: 假如我们要比较两个字符串是否相等. 在T串中查找S串.我们用最笨的方法去想,就是将T串与S串中的每一个元素一一去匹配,

【暑假】[实用数据结构]KMP

KMP算法 KMP算法是字符串匹配算法,可以在O(n)的时间完成,算法包含两部分,分别是:构造适配函数与两串匹配. 失配边的使用大大提高了算法效率,可以理解为已经成功匹配的字符不在重新匹配,因为我们已经知道它是什么,对应到算法中 匹配失败后应该在最大前缀之后继续匹配,因为某后缀已与最大前缀匹配成功而不用重新比较. 以下为代码实现: 1 const int maxn = 1000 + 5; 2 3 void getFail(char* P,int* f){ //构造失配边 4 int n=strl

大话数据结构——KMP算法(还存在问题)

http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html /*#include<iostream> #include <string> using namespace std; int count_same_char(string T,int j); void get_next(string T,int *next) { int j=1; next[1]=0; f

[数据结构] KMP的一个简单解释

1.概述 KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的. 给定两个字符串T和W,长度分别为m和n,判断W是否在T中出现,如果出现则返回出现的位置.常规方法是遍历T的每一个位置,然后从该位置开始和W进行匹配,但是这种方法的复杂度是O(mn).kmp算法通过一个O(n)的预处理,使匹配的复杂度降为O(m+n). 2.思路 我们要在 字符串T="ABCDABCDABDE"中查找 字符串W="ABCDABD"出现的位置. 很明显可以看出前6位都是匹

实验数据结构——KMP算法Test.ming

翻译计划 小明初学者C++,它确定了四个算术.关系运算符.逻辑运算.颂值操作.输入输出.使用简单的选择和循环结构.但他的英语不是很好,记住太多的保留字,他利用汉语拼音的保留字,小屋C++,发明了一种表达自己思想的算法描写叙述规则. 规则非常easy:他将開始程序头部以一个拼音名字标记,C++程序中的"{,}"用拼音"kaishi,jieshu"直观表示.选择和循环仅仅採用一种单一的结构,且保留字也分别用相应的拼音表示,只是在表示选择或循环条件时他去掉了多余的小括号:

数据结构——KMP算法

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

数据结构——KMP(串)

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

前端与算法 leetcode 28.实现 strStr()

# 前端与算法 leetcode 28.实现 strStr() 题目描述 28.移除元素 概要 这道题的意义是实现一个api,不是调api,尽管很多时候api的速度比我们写的快(今天这个我们可以做到和indexOf一样快),但我们还是要去了解api内实现的原理,在我们所熟悉的v8引擎中,indexOf使用了kmp和bm两种算法,在主串长度小于7时使用kmp,大于7的时候使用bm,bf咱就不说了哈,那个其实就是爆破算法, 提示 数据结构,kmp,bm 解析 kmp算法的核心其实就是动态规划,明确了