KMP (Knuth–Morris–Pratt) 算法是一种改进的字符串匹配算法,它的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。

题目:给定一个 T 字符串和一个 P 字符串,在 T 字符串中找出 P 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例:

T="ABABCABABDE", P="ABABDE"

暴力匹配

遍历字符串 T,将其中的每个字符与 P 的首字符进行比较,

  1. 如果 T[i] == P[0],遍历 P,判断 P 中的每个字符是否与 S 中对应位置的字符相等。若都相等,返回 i;否则进行下一步。
  2. 如果不相等,递增 i。再进行步骤 1,直至 T 遍历结束。

下面是C++代码实现:

int strMatch(string T, string P){int n = T.size();int m = P.size();if(m==0) return 0;    // P为空字符串for(int i=0; i<n-m+1; ++i){int j=0;int k=i;for(; j<m; ++j, ++k){if(T[k]!=P[j]) break;}if(j==m){return i;}}return -1;
}

最坏情况下,比较次数为 (n−m+1)⋅m(n-m+1) \cdot m(n−m+1)⋅m。当 n>>mn>>mn>>m 时,时间复杂度为 O(nm)O(nm)O(nm)。

对于示例,使用暴力匹配的过程如下,每次都从 P 的首个字符进行比较:

(1)ABABCABABDEABABDE
(2)ABABCABABDEABABDE
(3)ABABCABABDEABABDE
(4)ABABCABABDEABABDE
(5)ABABCABABDEABABDE
(6)ABABCABABDEABABDE

KMP算法

如果使用 KMP 算法进行字符串匹配,可以利用匹配失败后的信息。对于给定示例,其过程如下:

(1)ABABCABABDE i=0ABABDE      j=0
(2)ABABCABABDE i=4ABABDE    j=2
(3)ABABCABABDE i=4ABABDE  j=0
(4)ABABCABABDE i=5ABABDE j=1

上面的 i 和 j 分别表示每一轮开始时,先比较 T[i] 和 P[j]。
可以看到,从第(1)步知道,T 中的第二个 AB 子串不能与 P 的第二个 AB 子串匹配。
因为 P 中有两个 AB 子串,所以在第(2)步中,直接将 T 中的第二个 AB 子串与 P 的第一个 AB 子串进行匹配,再比较后续对应的字符。

构造 next 数组

next[i] 表示 P[0…i - 1] 子串的最长公共前缀后缀的长度。令 next[0] = -1。

对于示例,next 数组对应的值如下,其中第 1 列表示 next[i] 的值,第 2 列表示 P 的子串:

-1
0  A
0  AB
1  ABA
2  ABAB
0  ABABD

构造 next 数组的C++代码实现如下:

void getNext(string& s, vector<int>& next){int n = s.size();if(n==0) return;next.resize(n);next[0] = -1;int t = -1;int i = 0;while(i<n-1){if(t==-1 || s[t]==s[i]){++t;++i;next[i] = t;}else{t = next[t];}}
}

KMP算法实现

解题思路:

  • 求出 next 数组。
  • 初始时,令 i=j=0,i 和 j 分别指向 T 和 P 中的字符。
    ①若此时 T 和 P 中的字符匹配,则继续比较它们的下一位,即 ++i, ++j;
    ②否则 j=next[j],因为此时,根据 next 数组的性质,T[i-j, i-1] 和 P[0, j-1] 这两个子串是匹配的。

C++代码实现如下:

int strMatch(string& T, string& P){int n = T.size();int m = P.size();if(m==0) return 0;vector<int> next;getNext(P, next);int i=0, j=0;while(i<n && j<m){if(j<0 || T[i]==P[j]){++i;++j;}else{j = next[j];}}if(j==m){    // 匹配成功return i-j;}return -1;
}

KMP 算法的时间复杂度为 O(n+m)O(n+m)O(n+m),空间复杂度为 O(m)O(m)O(m)。


刷题题解目录

字符串匹配算法:KMP算法相关推荐

  1. 【GO语言实现字符串匹配算法-KMP算法】

    [GO语言实现字符串匹配算法-KMP算法] KMP算法原理说明: KMP算法是一种改进的字符串匹配算法,是有D.E.Knuth,J.H.Morris和V.R.Pratt提出的,所以被称为KMP算法. ...

  2. 字符串匹配算法KMP算法

    数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多 ...

  3. js实现kmp算法_字符串匹配算法KMP算法

    数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多 ...

  4. 字符串匹配算法——KMP算法学习

    KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...

  5. [Algorithm] 字符串匹配算法——KMP算法

    1 字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串& ...

  6. 浅析字符串匹配算法——KMP算法(附CF 535D-Tavas and Malekas)

    引入 在计算机中,人类的语言.文字等往往利用字符串进行保存,而字符串的匹配也对人们的生活产生着举足轻重的作用,例如个人信息的匹配.搜索引擎的使用等,为了在庞大的数据中找到我们所需的数据,字符串匹配的效 ...

  7. 数据结构(C语言版)严蔚敏(字符串的模式匹配算法--KMP算法)

    数据结构(C语言版)严蔚敏(字符串的模式匹配算法–KMP算法) 1.暴力匹配算法 // 暴力匹配算法 int Index2(SString S,SString T) {// S是主串,T是子串int ...

  8. c++ 字符串匹配算法sunday算法

    sunday 算法是一种很高效的字符串匹配算法, 其实现也较kmp算法简单很多 class Sunday {public:const string& needle;int mp[300];Su ...

  9. 字符串匹配算法——暴力算法

    字符串匹配算法--暴力算法,简称BF(BruteForce)BF(Brute\:Force)BF(BruteForce)算法. 基本思想:从主串(str)(str)(str)的第一个字符开始和子串(p ...

  10. 0x15.基本数据结构 — 字符串 (KMP算法(含详细证明)和最小表示法)

    目录 一.KMP模式匹配 1.引理: 2.引理证明: 3.使用优化的算法计算nextnextnext数组: 4.luogu P3375 [模板]KMP字符串匹配 5.UVA1328 Period 6. ...

最新文章

  1. 一步步写STM32 OS【二】环境搭建
  2. td 中连续数字或连续英文内容不自动换行
  3. js时间-价格-排序案例____冒泡排序实例
  4. spring mvc 配置解析之xml
  5. EMOS1.3安装后的相关安全设置
  6. AI产品,如何做好从零到一
  7. 不以跬步无以致千里——Day1
  8. 1-Java基础语法-Java初识
  9. do_fork实现--上
  10. MS SQL Server对表的设计修改时不允许保存
  11. matlab神经网络训练方法,matlab神经网络训练图
  12. CSS CSS3 pdf 电子书大全 百度云
  13. 企业信息化有哪些好处?
  14. Google开源C++单元测试框架gTest 5:死亡测试
  15. 专属于程序员的理财建议,抱走不谢
  16. java连接redis存取数据(详细)
  17. PHP快手直播弹幕采集,获取斗鱼弹幕php版(原创)
  18. AES - Openssl AES 函数说明
  19. 安兔兔电脑ssd测试软件,威钰战国NVMe SSD测评,安兔兔SSD测试软件到底靠不靠谱...
  20. Docker(一):什么是Docker?

热门文章

  1. 三一七事变——Windows 与 Linux 的纠缠
  2. AirPods无法充电怎么办?AirPods 无法充电的解决方法
  3. Java数组的定义与使用
  4. 【基础篇】MySQL
  5. 编译原理的学习 No.1
  6. [转]男人感悟100条
  7. 主流解压缩软件有哪些?这四款可以满足你的所有需求
  8. 人生情长特别栏目《大姐的幸福》定制护肤还原肌肤本态
  9. ubuntu 没有声音以及声音图标消失解决办法
  10. C++最小二乘拟合 (高阶最小二乘拟合)(附C++代码)