leetcode28. Implement strStr() (以及个人对KMP算法理解)
kmp算法标准板子题
class Solution {
public:vector<int> getNext(string needle){vector<int> next(needle.length());int k = -1 ;int j = 0;next[0] = -1;while(j < needle.length()-1){if(k == -1 || needle[j] == needle[k])next[++j] = ++k;elsek = next[k];}return next;}int strStr(string haystack, string needle) {int m = haystack.length();int n = needle.length();if(n == 0) return 0;int i = 0, j = 0;vector<int> next = getNext(needle);while(i < m && j < n){if(j == -1 || haystack[i] == needle[j]){i++;j++;}elsej = next[j];}if(j == n)return i - j;elsereturn -1;}
};
在这里记录一下KMP算法的理解
1.KMP是什么
对于主串a搜素子串b的问题:
暴力搜索的复杂度为O(主串长度*模式串长度)
暴力搜索就是a[i] != b[j]时
j = 0;
i = i - j + 1;
这样做效率极低。
如果利用KMP来做,时间复杂度O(m+n)为线性复杂度,已经是最低的了
2.KMP为什么这么做
以下面这个图为例,KMP算法的核心在于,当最后一位C与D无法匹配时,这时候有个隐含信息,就是匹配串的前三位ABA已经和主串的对应三位ABA匹配过,可能留下了一些匹配信息
如果拿之前的暴力搜索来看,最后一位C与D无法匹配时,
j会重置为0,i会变为1
B与A不匹配,j重置,i变为2;
然后比较B与C
像j=0与i=1匹配不上再移位的这种操作耗费了大量时间,我们能不能直接跳到上面这张j=0与i=2的比较图呢?
答案是肯定的,KMP算法就是利用了这个特性,当模式串的某一位不再匹配时,对于模式串不用重新从0开始,而是让i不变,j之前的模式串与主串刚好匹配就行。这样就省略了暴力搜索中需要j归零的操作。
3.KMP具体怎么做:
难点在于得出当子字符串的某一位无法匹配时,j变为多少
其实稍微分析一下就能看出结果
1.模式串的第一位就与主串不匹配,这时候需要原字符串的指针右移,用j = -1来表示,主要程序遇到j=-1表示i需要右移了。
2.模式串的第二位不匹配,j需要归零
3.模式串的第j位不匹配(j>1),这个时候就用了下面的这个公式进行递推
next[0] = -1;while(j < s.length()-1){if(k == -1 || s[j] == s[k])next[++j] = ++k;elsek = next[k];}
这个公式的具体解释可见https://www.cnblogs.com/yjiyjige/p/3263858.html
换句话说,如果前一位字符和前一位要跳转到的字符相同,那么后面这一位的跳转位置就是前一位的跳转位置+1;
好了,现在知道这个对我们找出每一位的跳转位置有什么用呢?
对于前一位字符和前一位要跳转到的字符相同的情况,可以直接利用下面的公式进行递推
if(k = next[j] && s[k] == s[j])next[j+1] = k + 1;
对于s[k]与s[j]不相等的情况,上面贴出来的这篇文章根本没讲清楚。
我们可以这样想,首先next[j+1]肯定不在C的后面,可以用反证法证明:
假如在C的后面,那么j+1的前面一定是ABAC.......ABAB,这个与之前的next[j] = k矛盾,因为最长的前缀是ABA而不是ABAC......ABA,所以,next[j+1]可能的位置一定在C的前面
然后,这时候就是模式串ABAC与被匹配串ABAB....的最后一位冲突了而需要移位寻找BAB,AB或B的情况,所以
k = next[k]
5.关于为什么KMP算法不好理解的个人感受
KMP算法其实经历了好几个难点,只不过很多地方没把这些难点讲清楚。
暴力搜索的优化(难点1)
匹配失败后指针所移动到的位置的计算(难点2)
s[k]与s[j]不相等时next[++j]的计算(难点3)
leetcode28. Implement strStr() (以及个人对KMP算法理解)相关推荐
- KMP算法理解(转)
(作者matrix67) KMP算法是拿来处理字符串匹配的.换句话说,给你两个字符串,你需要回答,B串是否是A串的子串(A串是否包含B串).比如,字符串A="I'm matrix67&quo ...
- KMP算法理解(参考BILIBILI正月点灯笼)
前言 KMP算法最近看了很多的博客和视频始终没有清楚理解NEXT数组的构建,在B站看到正月点灯笼大神的视频,里面提出的前缀表对我有很大启发,今天来记录分享一下. BILIBILI 正月点灯笼 定义 s ...
- KMP算法理解(超简洁-易懂代码)
文章目录 KMP算法 1. 暴力做法是怎么做的 1.1 时间复杂度: O(n^2) 2. 怎么去优化它 2.1 一般情况: 2.2 原理: 2.3 匹配过程 2.4 kmp 匹配的实现代码 2.5 n ...
- leetcode28 Implement strStr() 在字符串中寻找目标字符串
题目要求: 在子字符串中寻找目标字符串,并返回该字符串第一次出现时的下标 在尝试的写了一提中等难度的题目后,又一次回到简单难度的题寻找温暖T-T 思路一 在原字符串中中寻找目标字符串首字母的下标,并提 ...
- leetcode28.实现strStr()--简单词学KPM算法
class Solution {public int strStr(String haystack, String needle) {if(needle.isEmpty()) return 0;int ...
- 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)
图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...
- 【数据结构】详解KMP算法
字符串匹配算法:简单来说就是给你一个主串和一个子串,让你查找子串在主串中的位置,找到返回下标. 常见的两种算法:BF算法.KMP算法 这两种算法是怎样的思路呢,我们接着往下看: 目录 BF算法(暴力算 ...
- 【To Do】LeetCode 28. Implement strStr() 和KMP算法
LeetCode 28. Implement strStr() Solution1:我的答案 有投机取巧之嫌啊~ 注意string中的查找函数在查找时 参考网址:https://www.cnblogs ...
- leetcode28. 实现 strStr(KMP详解)
一:题目 二:思路 三:上码 // class Solution {// public: // int strStr(string haystack, string needle) {// if (n ...
最新文章
- Android 替换TextView 里面指定的符号
- LPC1768基本输入输出GPIO使用
- WordCount案例
- 增强for循环之删除
- boost::boost::directed_graph用法的测试程序
- asp.net core 自定义 Content-Type
- python 斐波那契数列 yield_Python中的yield到底是个什么鬼?
- iOS开发证书和配置文件的使用
- 老程序员为什么从不使用 Java 自带的序列化?
- 【数字基带信号】基于matlab数字基带信号波形仿真【含Matlab源码 988期】
- 计算机毕业论文答辩申请书,论文答辩申请书范文6篇
- Vivado2018.3手把手详细下载
- 代理模式和装饰者模式区别
- 2020年十大数字客户体验(CX)软件平台
- Win10 C盘清理的技巧,将C盘中除Windows外的所有系统文件夹移到C盘之外,节约大部分C盘空间
- iOS 卡顿原因及优化思路
- eclipse wifi 连接手机
- jQuery搜索高亮显示
- 物联网应用技术竞赛 ——数据库添加新用户映射
- 解决文件名是中文时的下载乱码问题