数据结构-kmp算法
定义 改进字符串的匹配算法
关键:通过实现一个包含了模式串的局部匹配信息的next()函数,利用匹配失败的信息,减少匹配次数。
1.BF算法 暴力匹配
给定 文本串S “BBC ABCDAB ABCDABCDABDE” 存储为 s[i] 和模式串 P “ABCDABD” 存储为p[j] 进行匹配
思路
p串与S串逐一匹配 ,不匹配则 p串右移一位,匹配下一个 。


p串不断右移 直到第四位匹配成功


不断向后匹配 直到失败

i,j回退到p串在s串的初始位置,p串右移匹配下一位。

暴力代码:
int ViolentMatch(char* s, char* p)
{
int sLen = strlen(s);
int pLen = strlen(p); int i = 0;
int j = 0;
while (i < sLen && j < pLen){
if (s[i] == p[j]){ //①如果当前字符匹配成功(即S[i] == P[j]),则i++,j++
i++;
j++;
}
else{// ②如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0
i = i - j + 1;
j = 0;
}
}
if (j == pLen)//匹配成功,返回模式串p在文本串s中的位置,否则返回-1
return i - j;
else
return -1;
}
2. kmp算法 优化匹配(利用next() 优化)
KMP算法和BF算法的“开局”是一样的,同样是把主串和模式串的首位对齐,从左到右对逐个字符进行比较。
第一轮,模式串和主串的第一个等长子串比较,发现前5个字符都是匹配的,第6个字符不匹配,是一个“坏字符”:
这时候,如何有效利用已匹配的串 “GTGTG” 呢?
我们可以发现,在串GTGTG”当中,后三个字符“GTG”和前三位字符“GTG”是相同的:
在下一轮的比较时,把这两个相同的片段对齐,出现匹配。 GTG 是串GTGTG 前缀后缀公共元素中最长的
第二轮,我们直接把模式串向后移动两位,让两个“GTG”对齐,继续从刚才主串的坏字符A开始进行比较:
显然,主串的字符A仍然是坏字符,这时候已经匹配的串缩短成了GTG:

按照第一轮的思路,我们来重新确定 前缀后缀最长公共元素:

第三轮,我们再次把模式串向后移动两位,让两个“G”对齐,继续从刚才主串的坏字符A开始进行比较:
以上就是KMP算法的整体思路:在已匹配的串当中寻找到 前缀后缀最长公共元素,在下一轮直接把两者对齐,从而实现模式串的快速移动。
3.求出next()函数的方式
①寻找前缀后缀最长公共元素长度
基本概念:
字符串abcda为例子
前缀 : 最后一个字符以外,一个字符串的全部头部组合。 例子abcda的前缀为 a ab abc abcd
后缀 : 第一个字符以外,一个字符串的全部尾部组合。 例子abcd的后缀为 bcda cda da a
前缀后缀最长公共元素 : 前缀后缀相同的元素,且长度最长的一个。例子的共同元素为a 长度为1
给定一个模式串 GTGTGCF
G无前缀后缀 公共元素长度为0
GT 前缀 G 后缀T公共元素长度为0
GTG 前缀G GT 后缀 TG G 公共元素G 长度为1
GTGT前缀 G GT GTG 后缀 TGT GT G 公共元素 GT 长度为 2
GTGTG 前缀G GT GTG GTGT 后缀 TGTG GTG TG G 公共元素GTG 长度为3
GTGTGC 前缀G GT GTG GTGT GTGTG 后缀 TGTGC GTGC TGC GC C 公共元素长度为0
GTGTGCF 前缀G GT GTG GTGT GTGTG GTGTGC 后缀 TGTGCF GTGCF TGCF GCF CF公共元素长度为0
得到串的 前缀后缀最长公共元素长度 如表
各个子串的最后一位对应该串的 最长公共元素长度

②求next数组
next数组 是一维整型数组,数组的下标代表了“已匹配串的长度 也是 已匹配串的下一位置 ”,
元素的值则是“ 已匹配串 前缀后缀最长公共元素 的长度 也是 已匹配串 前缀后缀最长公共元素 的下一个位置”。
通过next数组即可将公共元素部分对齐

void GetNext(char* p,int next[])
{
int pLen = strlen(p);
next[0] = 0;
int k = -1;
int j = 0;
while (j < pLen - 1)
{
//p[k]表示前缀,p[j]表示后缀
if (k == -1 || p[j] == p[k])
{
++k;
++j;
next[j] = k;
}
else
{
k = next[k];
}
}
}
代码
int KmpSearch(char* s, char* p)
{
int i = 0;
int j = 0;
int sLen = strlen(s);
int pLen = strlen(p);
while (i < sLen && j < pLen)
{
//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if (j == -1 || s[i] == p[j])
{
i++;
j++;
}
else
{
//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
j = next[j];
}
}
if (j == pLen)
return i - j;
else
return -1;
}
4 kmp对next()的进一步优化
扩展算法
1.BM算法
2 study算法
数据结构-kmp算法的更多相关文章
- 数据结构--KMP算法总结
数据结构—KMP KMP算法用于解决两个字符串匹配的问题,但更多的时候用到的是next数组的含义,用到next数组的时候,大多是题目跟前后缀有关的 . 首先介绍KMP算法:(假定next数组已经学会, ...
- 实验数据结构——KMP算法Test.ming
翻译计划 小明初学者C++,它确定了四个算术.关系运算符.逻辑运算.颂值操作.输入输出.使用简单的选择和循环结构.但他的英语不是很好,记住太多的保留字,他利用汉语拼音的保留字,小屋C++,发明 ...
- 数据结构——KMP算法
算法介绍 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法).KMP算法的核心是利用 ...
- <数据结构>KMP算法
next数组 定义 严格定义:next[i]表示使子串s[0...k] == s[i-k...i]的最大的k(前后缀可以重叠,但不能是s[0..i]本身) 含义:最长相等前后缀的下标,没有则赋-1 图 ...
- 大话数据结构——KMP算法(还存在问题)
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html /*#include& ...
- 数据结构KMP算法中手算next数组
总结一下今天的收获(以王道数据结构书上的为例子,虽然我没看它上面的...):其中竖着的一列值是模式串前缀和后缀最长公共前缀. 最后求得的结果符合书上的结果,如果是以-1开头的话就不需要再加1,如果是以 ...
- 数据结构- 串的模式匹配算法:BF和 KMP算法
数据结构- 串的模式匹配算法:BF和 KMP算法 Brute-Force算法的思想 1.BF(Brute-Force)算法 Brute-Force算法的基本思想是: 1) 从目标串s 的第一个字 ...
- 数据结构与算法--KMP算法查找子字符串
数据结构与算法--KMP算法查找子字符串 部分内容和图片来自这三篇文章: 这篇文章.这篇文章.还有这篇他们写得非常棒.结合他们的解释和自己的理解,完成了本文. 上一节介绍了暴力法查找子字符串,同时也发 ...
- 【数据结构】KMP算法
我还是不太懂... 转2篇大神的解释 1>https://www.cnblogs.com/yjiyjige/p/3263858.html 2>https://blog.csd ...
随机推荐
- 你真会看idea中的Log吗?
在项目中提交代码时,我们时常忘了自己是否已经update代码或者push代码了,或者以为自己push,但是别人说你的代码没push,其实可以通过idea的Log日志中查看,你会发现里面有三种颜色的标签 ...
- 【MyBatis】MyBatis 多表操作
MyBatis 多表操作 文章源码 一对一查询 需求:查询所有账户信息,关联查询下单用户信息. 注意:因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询.如果从用户 ...
- DTCC 2020 | 阿里云李飞飞:云原生分布式数据库与数据仓库系统点亮数据上云之路
简介: 数据库将面临怎样的变革?云原生数据库与数据仓库有哪些独特优势?在日前的 DTCC 2020大会上,阿里巴巴集团副总裁.阿里云数据库产品事业部总裁.ACM杰出科学家李飞飞就<云原生分布式数 ...
- (十一)time模块
三种时间表示 在Python中,通常有这几种方式来表示时间: 时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行"ty ...
- 【Linux】shell脚本实现多并发
情景 shell脚本的执行效率虽高,但当任务量巨大时仍然需要较长的时间,尤其是需要执行一大批的命令时.因为默认情况下,shell脚本中的命令是串行执行的.如果这些命令相互之间是独立的,则可以使用&qu ...
- Over Permission - Pikachu
概述: 如果使用A用户的权限去操作B用户的数据,A的权限小于B的权限,如果能够成功操作,则称之为越权操作. 越权漏洞形成的原因是后台使用了不合理的权限校验规则导致的. 一般越权漏洞容易出现在权限页面( ...
- hive窗口函数/分析函数详细剖析
hive窗口函数/分析函数 在sql中有一类函数叫做聚合函数,例如sum().avg().max()等等,这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚集前的行数的.但是有时 ...
- Java优先队列PriorityQueue的各种打开方式以及一些你不知道的细节
目录 Java优先队列PriorityQueue的各种打开方式以及一些你不知道的细节 优先队列的默认用法-从小到大排序 对String类用优先队列从大到小排序 通过自定义比较器对自定义的类进行从小到大 ...
- Zerotier在windows下实现内网远程桌面
Zerotier实现内网远程桌面 使用背景 实验室设备条件过于恶劣 向日葵在有些场景下会莫名崩溃,或者画面不动. Teamviewer免费版在之前用的时候出现过疑似商业行为被断连,github上寻解决 ...
- vercel是什么神仙网站?
Vercel? vercel是我用过的最好用的网站托管服务.本网站就是基于hexo引擎模板开发,托管在vercel上的. vercel类似于github page,但远比github page强大,速 ...