2021-02-03:手写代码:KMP算法。
福哥答案2021-02-03:
Knuth-Morris-Pratt 字符串查找算法,简称为 KMP算法,常用于在一个文本串 S 内查找一个模式串 P 的出现位置。
这个算法由 Donald Knuth、Vaughan Pratt、James H. Morris 三人于 1977 年联合发表,故取这 3 人的姓氏命名此算法。
下面直接给出 KMP算法 的操作流程:
1.假设现在文本串 S 匹配到 i 位置,模式串 P 匹配到 j 位置。
2.如果 j = -1,或者当前字符匹配成功(即 S[i] == P[j] ),都令 i++,j++,继续匹配下一个字符。
3.如果 j != -1,且当前字符匹配失败(即 S[i] != P[j] ),则令 i 不变,j = next[j]。此举意味着失配时,模式串 P相对于文本串 S 向右移动了 j - next [j] 位。
4.换言之,将模式串 P 失配位置的 next 数组的值对应的模式串 P 的索引位置移动到失配处。
注意点:
1.字符串的位置一定是右移,不会左移。
2.匹配串的位置是一位一位的右移,左移是根据next数组。
3.字符串和匹配串的某个位置不等的时候,优先匹配串位置左移,左移不动的时候,字符串位置才右移。
代码用golang编写,代码如下:
func strStr(haystack string, needle string) int {
if len(needle)<=0{
return 0
}
return GetIndexOf(haystack,needle)
}
func GetNextArray(match string) []int {
matchLen := len(match)
if matchLen == 1 {
return []int{-1}
}
next := make([]int, matchLen)
next[0] = -1
next[1] = 0
i := 2
// cn代表,cn位置的字符,是当前和i-1位置比较的字符
cn := 0
for i < matchLen {
if match[i-1] == match[cn] { //匹配
cn++
next[i] = cn
i++
} else if cn > 0 {
cn = next[cn] //可回退指针
} else {
next[i] = 0
i++
}
}
fmt.Println("next = ", next)
return next
}
func GetIndexOf(s string, m string) int {
sLen := len(s)
mLen := len(m)
if sLen < len(m) {
return -1
}
next := GetNextArray(m)
x := 0 //从来不回退
y := 0 //根据next数组回退
for x < sLen && y < mLen {
if s[x] == m[y] {
x++
y++
} else if next[y] == -1 {
x++
} else {
y = next[y] //回退了
}
}
if y == mLen {
return x - y
} else {
return -1
}
}
执行结果如下:
***
[力扣28. 实现 strStr()](https://leetcode-cn.com/problems/implement-strstr/)
[左神的KMP算法的java代码,我的golang代码参考了这个](https://github.com/algorithmzuo/algorithmbasic2020/blob/master/src/class27/Code01_KMP.java)
2021-02-03:手写代码:KMP算法。的更多相关文章
- .netER的未来路,关于基础是否重要和应该自己手写代码吗?
http://www.cnblogs.com/onepiece_wang/p/5558341.html#!comments 引用"基础知识的学习,一开始可能是背书,但是在后续若干年的工作过程 ...
- ClownFish:比手写代码还快的通用数据访问层
http://www.cnblogs.com/fish-li/archive/2012/07/17/ClownFish.html 阅读目录 开始 ClownFish是什么? 比手写代码还快的执行速度 ...
- 手写代码自动实现自动布局,即Auto Layout的使用
手写代码自动实现自动布局,即Auto Layout的使用,有需要的朋友可以参考下. 这里要注意几点: 对子视图的约束,若是基于父视图,要通过父视图去添加约束. 对子视图进行自动布局调整,首先对UIVi ...
- 如果选择构建ui界面方式,手写代码,xib和StoryBoard间的博弈
代码手写UI这种方法经常被学院派的极客或者依赖多人合作的大型项目大规模使用. 大型多人合作项目使用代码构建UI,主要是看中纯代码在版本管理时的优势,检查追踪改动以及进行代码合并相对容易一些. 另外,代 ...
- 手写代码UI,xib和StoryBoard间的的优劣比较
在UI制作方面,逐渐分化三种主要流派:使用代码手写UI:使用单个xib文件组织viewController或者view:使用StoryBoard来通过单个或很少的几个文件构建UI.三种方式各有优劣,也 ...
- UI到底应该用xib/storyboard完成,还是用手写代码来完成?
UI到底应该用xib/storyboard完成,还是用手写代码来完成? 文章来源:http://blog.csdn.net/libaineu2004/article/details/45488665 ...
- 2019前端面试系列——JS高频手写代码题
实现 new 方法 /* * 1.创建一个空对象 * 2.链接到原型 * 3.绑定this值 * 4.返回新对象 */ // 第一种实现 function createNew() { let obj ...
- Appium初始化设置:手写代码连接手机、appium-desktop连接手机
一.包名获取的三种方式 1)找开发要2)mac使用命令:adb logcat | grep START win使用命令:adb logcat | findstr START 或者可以尝试使用第3条命令 ...
- gcd手写代码及STL中的使用方法
一.手写代码 inline int gcd(int x,int y){ if(y==0) return x; else return(gcd(y,x%y)); } 二.STL中的使用方法 注:在STL ...
- SpringCloud-Ribbon负载均衡机制、手写轮询算法
Ribbon 内置的负载均衡规则 在 com.netflix.loadbalancer 包下有一个接口 IRule,它可以根据特定的算法从服务列表中选取一个要访问的服务,默认使用的是「轮询机制」 Ro ...
随机推荐
- Mitmproxy 拦截、mock移动设备网络请求
转载于https://blog.csdn.net/countofdane/article/details/82055173 1. 安装 pip install mitmproxy 2. 启动 mi ...
- 给jui(dwz)的navTab换一套漂亮的图标
上次讲了给jui(dwz)的菜单树换一套漂亮的图标,这次讲一下在点击菜单后,怎么把设置的漂亮图标带到navTab上去. 官方的navTab是这样显示的,除了默认的我的主页外,tab页上只有标题没有图标 ...
- 理解Map-构建关联数组
理解Map 要更深入理解map,学习如何构建关联数组是很有帮助的,以下是简单实现 package org.example.onjava.senior.example03collection.map; ...
- CentOS /RHEL 系统更新安全补丁的方法
在 Linux 系统上,其中一个最重要的需求就是保持定期更新最新的安全补丁,或者为相应的 Linux 版本更新可用的安全补丁.在这篇文章中,我们将分享如何在 CentOS/RHEL 7/6 版本中设置 ...
- 文件的上传&预览&下载学习(一)
注:主要是说明后端逻辑和数据库表设计 1.当前主流的几种文件上传&预览&下载方式 把文件直接存储在服务器 分布式存储OSS,比如阿里OSS.Minio 2.数据库表设计 由于文件都是跟 ...
- Java8 获取当天日期的前一天
LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
- 微软wsl2启用天父行程systemd
默认情况下 微软wsl2的天父行程是init,没办法使用systemctl相关指令,所以想使用天父行程 systemd. 本文以Wsl2 Alma Linux为例,启用systemd 上帝与你同在,阿 ...
- VS2013连接SQLSERVER数据库时显示无法添加数据连接
VS2013连接sqlserver2008时出现如下错误: VS2013添加Microsoft SQL Server数据源时,会遇到无法添加数据连接. Could not load file or a ...
- dart基础---->函数传值
1. string type main(List<String> args) { String name = "huhx"; changIt(name); print( ...
- C#中抽象方法与虚方法的区别详解及示例
1. 抽象方法与虚方法的区别 先说两者最大的区别:抽象方法是需要子类去实现的.虚方法是已经实现了的,可以被子类覆盖,也可以不覆盖,取决于需求.因为抽象类无法实例化,所以抽象方法没有办法被调用,也就 ...