一个简易的kmp教学并给出java实现
简单介绍一下问题
给定source字符串,找出target字符串出现的首位
例如
source 为“abddabddabc”
target 为 “abddabc”
从第一位开始比较 |a b d d a b|d d a b c
|a b d d a b|c 不匹配
从第二位继续比较 a|b d d a b d d a b c
|a 不匹配
。。。
。。。
从第五位继续比较 a b d d|a b d d a b c
a b d d a b c 匹配成功
再给出kmp算法
从第一位开始比较 a b d d a b|d d a b c
a b d d a b|c 不匹配
————————————————————————————————
观察失配处前两位ab与target的前两位ab一致,
而整个target不再出现ab,所以即使出现匹配,也只能出现在最后两位
也就是ab之后,所以我们可以直接跳过中间所有位
直接把target的前两位与source当前ab对齐,继续匹配
————————————————————————————————
第二次匹配 a b d d| a b|| d d a b c
| a b||d d a b c
其中单斜杠处即为所求 双斜杠处为第二次匹配起始位
在上个例子 两条长横线中的内容就是kmp的核心思路:
不需要每一次失配都只从下一位继续,
只需要对比首位的重合部分,移动target,使其首尾重合部分对其,即可继续对比
再举一个极端的例子,便于理解
target 为 abcdefgh
如果source存在匹配部分,那这部分必由a起始
所以在匹配的过程中,发生了失配,即可全部跳过,对比下一位是否为a
而对于首尾有重合部分,则需要从重合部分下一位开始,而重合部分的起始位即为所求
重新用自然语言描述一下我们要做的事:
1 开始匹配 如果完成匹配 返回重合的起始位
2 发生失配 从当前失配位 观察target的首尾重合部分
3 调整target到重合部分首位 从失配位继续匹配
而失配位前target的首尾重合部分的长度由target自身决定,举例说明
a b d d a b d d a b c
0 1 2 3 4 5 6 7 8 9 10
0 0 0 0 1 2 3 4 1 2 0
比如当source为
a b d d a b d d c c c c c c c c c
0 1 2 3 4 5 6 7 8 9 10
0 0 0 0 1 2 3 4 1 2 0
a b d d a b d d a b c
我们在第八位发生失配,那么在0+8-4位为起始,从target的4 位继续匹配即可
下面给出java代码实现:
public static void main(String[] args) {
String source="abddabkdabc";
String target="abddabc";
int a=Solution.strStr(source, target);
System.out.println(a);
}
public static int strStr(String source, String target) {
if(target=="") {
return 0;
}
if(source.length()<target.length()) {
return -1;
}
int[] next=nextKmp(target);
int j=0;
int i=0;
while(true){
while(j<target.length()&&(i+j)<source.length()&&source.charAt(i+j)==target.charAt(0+j)) {
//System.out.println(source.charAt(i+j));
j++;
}
if(j==target.length()) {
System.out.println("!");
return i;
}
if((i+j)==source.length()) {
return -1;
}
if(j==0) {
i++;
continue;
}
i=i+j-next[j-1];
j=next[j-1];
}
}
if(str.equals("")) {
return null;
}
int[] next=new int[str.length()];
for (int i = 0; i < next.length; i++) {
next[i]=0;
}
for (int i = 1; i < str.length(); ) {
int j=0;
while((i+j)<str.length()&&str.charAt(i+j)==str.charAt(0+j)) {
next[i+j]=j+1;
j++;
}
if(j==0) {
i++;
}else {
i+=j;
}
}
return next;
}
}
一个简易的kmp教学并给出java实现的更多相关文章
- Java实践:一个简易的http server和client的java源码学习和总结。
一.基本思路: 1.服务器端通过socket(), 监听在TCP 8080端口,等待客户端来连接. 2.服务器端解析客户端的HTTP请求中的URI值,把本地的目录下指定文件通过java的读取文件的方式 ...
- .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”
FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...
- 自己来实现一个简易的OCR
来做个简易的字符识别 ,既然是简易的 那么我们就不能用任何的第三方库 .啥谷歌的 tesseract-ocr, opencv 之类的 那些玩意是叼 至少图像处理 机器视觉这类课题对我这种高中没毕业的人 ...
- 探秘Tomcat——一个简易的Servlet容器
即便再简陋的服务器也是服务器,今天就来循着书本的第二章来看看如何实现一个servlet容器. 背景知识 既然说到servlet容器这个名词,我们首先要了解它到底是什么. servlet 相比你或多或少 ...
- ENode 2.0 - 第一个真实案例剖析-一个简易论坛(Forum)
前言 经过不断的坚持和努力,ENode 2.0的第一个真实案例终于出来了.这个案例是一个简易的论坛,开发这个论坛的初衷是为了验证用ENode框架来开发一个真实项目的可行性.目前这个论坛在UI上是使用了 ...
- 使用MVVM框架avalon.js实现一个简易日历
最近在做公司内部的运营管理系统,因为与日历密切相关,同时无需触发条件直接显示在页面上,所以针对这样的功能场景,我就用avalon快速实现了一个简易日历,毕竟也是第一次造日历这种轮子,所以这里记录下我当 ...
- C 实现一个简易的Http服务器
引言 做一个老实人挺好的,至少还觉得自己挺老实的. 再分享一首 自己喜欢的诗人的一首 情景诗. 每个人总会有问题,至少喜欢就好, 本文 参照 http 协议 http://www.cnblogs. ...
- avalon.js实现一个简易日历
使用MVVM框架avalon.js实现一个简易日历 最近在做公司内部的运营管理系统,因为与日历密切相关,同时无需触发条件直接显示在页面上,所以针对这样的功能场景,我就用avalon快速实现了一个简 ...
- Tinychatserver: 一个简易的命令行群聊程序
这是学习网络编程后写的一个练手的小程序,可以帮助复习socket,I/O复用,非阻塞I/O等知识点. 通过回顾写的过程中遇到的问题的形式记录程序的关键点,最后给出完整程序代码. 0. 功能 编写一个简 ...
随机推荐
- sql的基本语法
一. 数据库 1.查询服务器上有哪些数据库 show databases; 2.新建数据库 create database TestSqlSugar; 3.进入数据库 use TestSqlSugar ...
- #Java学习之路——基础阶段二(第二篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- PHP全栈学习笔记15
PHP标记风格 PHP一共支持4种标记风格 <?php echo "这是XML风格的标记"; ?> 脚本风格 <script language="php ...
- 如何机智判断页面是刷新还是关闭,背景:vue项目,需求:关闭页面,下次直接跳到登陆页
最近项目有这么个需求:要在关闭当前系统的窗口的时候,退出登录, 因为如果不退出登录可能存在安全风险,其实我想说,电脑没事别借给别人活着离开工位记得一定要锁屏,其实我们设置了cookie失效时间的,过了 ...
- NormalDialogFragmentDemo【普通页面的DialogFragment】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 该Demo主要演示DialogFragment作为普通页面,显示全屏和状态栏下方的效果以及动画效果. 效果图 代码分析 @Overr ...
- SVN问题解决--Attempted to lock an already-locked dir
今天上午更新uap(uap就是基于eclipse开发的软件,可以当eclipse来使用)上的代码时,发现在svn上更新不了,一直报这个Attempted to lock an already-lock ...
- 滤波器——BoxBlur均值滤波及其快速实现
个人博客地址:滤波器--BoxBlur均值滤波及其快速实现 动机:卷积核.滤波器.卷积.相关 在数字图像处理的语境里,图像一般是二维或三维的矩阵,卷积核(kernel)和滤波器(filter)通常指代 ...
- Flink从入门到放弃(入门篇4) DataStreamAPI
戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...
- FastDFS分布式文件系统&Nginx负载均衡最小环境安装配置[超级详解]
1.背景 FastDFS 是一款开源的.分布式文件系统(Distributed File System),由淘宝开发平台部资深架构师余庆开发.该开源项目的主页是 http://code.google. ...
- Vue-zTree
在vue中引入zTree,和引入其他组件类似,首先在main.js里将以下3个js引入: import "./js/jquery-3.3.1.min.js";import &quo ...