通过图片对比带给你不一样的KMP算法体验
KMP 算法,俗称“看毛片”算法,是字符串匹配中的很强大的一个算法,不过,对于初学者来说,要弄懂它确实不易。
笔者认为,KMP 算法之所以难懂,很大一部分原因是很多实现的方法在一些细节的差异。体现在几个方面: next 数组,有的叫做“失配函数”,其实是一个东西; next 数组中,有的是以下标为 0 开始的,有的是以 1 开始的; KMP 主算法中,当发生失配时,取的 next 数组的值也不一样!就这样,各说各的,乱的很!
所以,在阐述我的理解之前,我有必要说明一下,我是用 next 数组的, next 数组是以下标 0 开始的!还有,我不会在一些基础的概念上浪费太多,所以你在看这篇文章时必须要懂得一些基本的概念,例如 “ 朴素字符串匹配 ”、“ 前缀 ” , “ 后缀 ” 等!
假设在我们的匹配过程中出现了这一种情况:

根据 KMP 算法,在该失配位会调用该位的 next 数组的值!在这里有必要来说一下next 数组的作用!说的太繁琐怕你听不懂,让我用一句话来说明:
返回失配位之前的最长公共前后缀!
好,不管你懂不懂这句话,我下面的文字和图应该会让你懂这句话的意思以及作用的!
首先,我们取之前已经匹配的部分(即蓝色的那部分!)

我们在上面说到 next 数组的作用时,说到 “ 最长公共前后缀 ” ,体现到图中就是这个样子!

接下来,就是最重要的了!

没错,这个就是 next 数组的作用了 :
返回当前的最长公共前后缀长度,假设为 len 。因为数组是由 0 开始的,所以 next数组让第 len 位与主串匹配就是拿最长前缀之后的第 1 位与失配位重新匹配,避免匹配串从头开始!如下图所示!

(重新匹配刚才的失配位!)
如果都说成这样你都不明白,那么你真的得重新理解什么是 KMP 算法了!
接下来最重要的,也是 KMP 算法的核心所在,就是 next 数组的求解!不过,在这里我找到了一个全新的理解方法!如果你懂的上面我写的的,那么下面的内容你只需稍微思考一下就行了!
跟刚才一样,我用一句话来阐述一下 next 数组的求解方法,其实也就是两个字:
继承
a 、当前面字符的前一个字符的对称程度为 0 的时候,只要将当前字符与子串第一个字符进行比较。这个很好理解啊,前面都是 0 ,说明都不对称了,如果多加了一个字符,要对称的话最多是当前的和第一个对称。比如 agcta 这个里面 t 的是 0 ,那么后面的 a 的对称程度只需要看它是不是等于第一个字符 a 了。
b 、按照这个推理,我们就可以总结一个规律,不仅前面是 0 呀,如果前面一个字符的 next 值是 1 ,那么我们就把当前字符与子串第二个字符进行比较,因为前面的是1 ,说明前面的字符已经和第一个相等了,如果这个又与第二个相等了,说明对称程度就是 2 了。有两个字符对称了。比如上面 agctag ,倒数第二个 a 的 next 是 1 ,说明它和第一个 a 对称了,接着我们就把最后一个 g 与第二个 g 比较,又相等,自然对称成都就累加了,就是 2 了。
c 、按照上面的推理,如果一直相等,就一直累加,可以一直推啊,推到这里应该一点难度都没有吧,如果你觉得有难度说明我写的太失败了。
当然不可能会那么顺利让我们一直对称下去,如果遇到下一个不相等了,那么说明不能继承前面的对称性了,这种情况只能说明没有那么多对称了,但是不能说明一点对称性都没有,所以遇到这种情况就要重新来考虑,这个也是难点所在。

如果蓝色的部分相同,则当前 next 数组的值为上一个 next 的值加一,如果不相同,就是我们下面要说的!
如果不相同,用一句话来说,就是:
从前面来找子前后缀
1 、如果要存在对称性,那么对称程度肯定比前面这个的对称程度小,所以要找个更小的对称,这个不用解释了吧,如果大那么就继承前面的对称性了。
2 、要找更小的对称,必然在对称内部还存在子对称,而且这个必须紧接着在子对称之后。
如果不能理解,那么看一下图吧!

好了,我已经把该说的尽可能以最浅显的话和最直接的图展示出来了,如果还是不懂,那我真的没有办法了!
说了这么多,下面是代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
void cal_next( char * str, int * next, int len )
{
int i, j;
next[] = -;
; i < len; i++ )
{
j = next[ i - ];
] != str[ i ] && ( j >= ) )
{
j = next[ j ];
}
] )
{
next[ i ] = j + ;
}
else
{
next[ i ] = -;
}
}
}
int KMP( char * str, int slen, char * ptr, int plen, int * next )
{
, p_i = ;
while( s_i < slen && p_i < plen )
{
if( str[ s_i ] == ptr[ p_i ] )
{
s_i++;
p_i++;
}
else
{
)
{
s_i++;
}
else
{
p_i = next[ p_i - ] + ;
}
}
}
;
}
int main()
{
};
};
int slen, plen;
int next[ N ];
while( scanf( "%s%s", str, ptr ) )
{
slen = strlen( str );
plen = strlen( ptr );
cal_next( ptr, next, plen );
printf( "%d\n", KMP( str, slen, ptr, plen, next ) );
}
;
}
通过图片对比带给你不一样的KMP算法体验的更多相关文章
- TwentyTwenty – 使用 jQuery 实现图片对比功能
这是一款非常棒的图片对比工具,能够方便的应用到你的网站中.其基本思路是把两张图片层叠在一起,当你拖动滑竿的时候,利用 CSS clip 裁剪图片,进行形成视觉对比效果. 您可能感兴趣的相关文章 Met ...
- 移植MonkeyRunner的图片对比和获取子图功能的实现-UiAutomator/Robotium篇
根据前一篇文章<移植MonkeyRunner的图片对比和获取子图功能的实现-Appium篇>所述,因为Appium和MonkeyRunner有一个共同点--代码控制流程都是在客户端实现的. ...
- 图片像素对比OpenCV实现,实现人工分割跟算法分割图像结果的对比
图片对比,计算不同像素个数,已经比率.实现人工分割跟算法分割图像结果的对比,但是只能用灰度图像作为输入 // imageMaskComparison.cpp : 定义控制台应用程序的入口点. // / ...
- Python 实现图片对比检测
在写测试框架的时候,需要用到图片对比的方法来判断用例执行的情况,问了一下度娘,原来可以用PIL模块处理: from PIL import Image # 先安装Pillow, \>pip in ...
- 使用Python的PIL模块来进行图片对比
使用Python的PIL模块来进行图片对比 在使用google或者baidu搜图的时候会发现有一个图片颜色选项,感觉非常有意思,有人可能会想这肯定是人为的去划分的,呵呵,有这种可能,但是估计人会累死, ...
- 云图说|DRS数据对比——带您随时观测数据一致性
摘要:数据迁移过程中,如何保证数据不丢失,确保数据的一致性? 本文分享自华为云社区<[云图说]第226期 DRS数据对比--带您随时观测数据一致性>,作者:阅识风云 . 数据迁移过程中,如 ...
- C#Qrcode生成二维码支持中文,带图片,带文字
C#Qrcode生成二维码支持中文带图片的操作请看二楼的帖子,当然开始需要下载一下C#Qrcode的源码 下载地址 : http://www.codeproject.com/Articles/2057 ...
- C# Qrcode生成二维码支持中文,带图片,带文字 2015-01-22 15:11 616人阅读 评论(1) 收藏
1.下载Qrcode库源码,下载地址:http://www.codeproject.com/Articles/20574/Open-Source-QRCode-Library 2.打开源码时,部分类库 ...
- java利用直方图实现图片对比
需求 实现两张图对比,找出其中不同的部分. 分析 首先将大图切片,分成许多小图片.然后进行逐个对比,并设定相似度阈值,判断是否是相同.最后整理,根据生成数组标记不同部分.如果切片足够小,便越能精确找出 ...
随机推荐
- Linux-wget
Linux系统中的wget是一个下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器.wget支持HTTP,HTTPS和FTP协 ...
- Django进阶2
一.ORM操作进阶 ForeignKey关联 示例models from django.db import models # Create your models here. class User(m ...
- 【转】创建SVN仓库的步骤
转载地址:http://www.cnblogs.com/ivan0626/p/3783053.html 今天在客户现场联调,两个开发人员之间的代码想用SVN来管理,所以就临时在本地机器上搭建一个S ...
- centos7下搭建nginx+php7.1+mariadb+memcached+redis
一.环境准备 1.首先介绍一下环境,以及我们今天的主角们 我用的环境是最小化安装的centos7,mariadb(江湖传言mysql被oracle收购后,人们担心像java一样毁在oracle手上于是 ...
- 我理解的webservice是这样的
本文来自 --迹忆:http://www.onmpw.com/tm/xwzj/network_45.html 最近在工作中遇到这样的一个项目(暂且定为项目A),项目A本身是用PHP开发的,但是其数据是 ...
- Nginx与Lua利用fpm打成rpm包
1.下载相关软件 需要软件有:Nginx,LuaJIT,ngx_devel_kit,ngx_lua等安装文件 安装Lua或者LuaJIT都是可以的,但是出于效率的考虑,推荐安装LuaJITshell& ...
- html5的新特性——拖放API
在HTML5之前只能使用鼠标事件模拟出"拖放"效果:HTML5专门为拖放提供了7个事件句柄. 被拖动的源对象可以触发的事件: (1)ondragstart:源对象开始被拖动 (2 ...
- UIButton的文本与图片的布局
UIButton内部文本和图片的布局是我们日常代码中,不可缺少的部分,按钮默认左边图片右边文本,那要实现左边文本,右边图片,我们该怎么解决呢,上面图片,下面文本又该怎么办呢 其实很简单,今天总结下,目 ...
- jquery.validate使用 - 自定义错误信息
自定义错误消息的显示方式 默认情况下,验证提示信息用label元素来显示, 并且会添加css class, 通过css可以很方便设置出错控件以及错误信息的显示方式. /* 输入控件验证出错*/form ...
- UE4 AI入门
转自:http://blog.csdn.net/u011707076/article/details/46607121 本文是翻译的官方文https://docs.unrealengine.com/l ...